So, I'm programming a game in python that has a lottery system. To this I have a function called lottery which is played whenever the lottery is used. This lottery system get a random number from 1 - 50 and then calls 1 of 50 lottery event functions which are every so slightly different.
The problem is that this function is basically unreadable, as it defines 51 separated functions, and the lottery function uses a list of 50 different if states to check which outcome it should use.
I've tried rewriting this code I don't know how many times now. First, I tried to refactor it using the built in typing module's overload descriptor, but overload requires the parameters to be different types for every different overload. This just led to me adding 50 different type classes which was even less efficient.
I then tried calling the function from the builtin globals dictionary, but my IDE would flag an error when running, even if the code worked. here's some pseudocode, since I no longer have the original code:
def lottery()
lotnumb = random number(range(50))
if lotnumb == 1:
lotevent1()
elif lotnumb == 2:
lotevent2()
elif lotnumb == 3:
lotevent3()
elif lotnumb == 4:
lotevent4()
elif lotnumb == 5:
lotevent5()
elif lotnumb == 6:
lotevent6()
elif lotnumb == 7:
lotevent7()
// this continues all the way to if statement number 50
CodePudding user response:
Passing function as an argument
def f_1():
print("1")
def f_2():
print("2")
def f_3():
print("3")
def f_4():
print("4")
def applyFunction(func):
func()
if __name__=="__main__":
f1= f_1
applyFunction(f1)
CodePudding user response:
You could easily put all the functions into a list and index it but if you want something more complex or just dont want to use them in a list here is a solution.
This seems to me like a situation where you could use a the __getattribute__
method in python classes. The way you could do this is by creating a lottery_event
class and within it define each of your functions.
It would look like this.
class LotteryEvents:
@staticmethod
def lotevent1():
pass
@staticmethod
def lotevent2():
pass
@staticmethod
def lotevent3():
pass
# and so on...
Then what you can do is use python's dunder method __getattribute__
to be able to access each function. Calling __getattribute__
with the name of the function you want to use will return that function. You can add this as a method in the class like so.
class LotteryEvents:
@classmethod
def getLotEvent(cls, num):
# gets the function and stores it to the variable loteventfunc
loteventfunc = cls.__getattribute__(f'lotevent{num}')
return loteventfunc
# you could just call it from here
@staticmethod
def lotevent1():
pass
@staticmethod
def lotevent2():
pass
@staticmethod
def lotevent3():
pass
# and so on...
# then to call it you do this
random_num = random.randint(0, 50)
func = LotteryEvents.getLotEvent(random_num)
func()
There are many other ways to solve this problem, but this is how I would most likely tackle something like this. It does not remove having to define each function but it does remove that awful mess of else ifs and looks cleaner. If it still takes up too much space in your file I would recommend putting this class into a separate file and importing it into your project. Even without this solution putting it all in a different file could help organize your code.
CodePudding user response:
Without knwoing more details about what is actually inside your loteventX
functions, what I can suggest you is to add them into a list and randomly choose one and call, from inside you lottery
function. Like this:
lottery_events = [
lotevent1,
lotevent2,
lotevent3,
lotevent1,
...
]
def lottery():
lotevent = random.choice(lottery_events)
lotevent()
However, I think there might be a simpler solution where you can parameterize your loteventX
functions and not need to implement each of them independently. Please share more details if you want to explore that option.
CodePudding user response:
import random
def f_1():
print("1")
def f_2():
print("2")
def f_3():
print("3")
def f_4():
print("4")
def applyFunction(func):
func()
if __name__=="__main__":
f_list = [f_1,f_2,f_3,f_4]
applyFunction(random.choice(f_list))