当函数具有不同数量的参数时从列表中调用随机函数

Calling random functions from a list when functions have different number of parameters

我是初学者,正在尝试编写基于文本的游戏,例如大富翁。自从我了解函数以来,我认为最好的方法是为每个方块定义一个函数。然后,我会将这些函数放在一个列表中并随机调用它们。问题是函数可能需要不同数量的参数或不需要参数。

from random import randrange

def foo1(param_of_foo1):
    x = param_of_foo1 + 1
    print "x is:", x

def foo2(param_of_foo2):
    y = param_of_foo2 + 2
    print "y is:", y

def foo3(useless_param):
    print "I have a parameter but I don't really need it..."

list_of_foo = [foo1, foo2, foo3]

arg = 0

function_index = randrange(0,3)

print "Function index is:", function_index

if function_index == 0:
    arg = 4

elif function_index == 1:
    arg = 10

list_of_foo [function_index](arg)

如您所见,这似乎可行,但不是一个完美的解决方案。当然,我不喜欢我必须用参数定义第三个函数,即使它不需要它。而且我也不喜欢我必须为某些函数指定一个条件,让它们知道它们应该使用什么作为参数。 当然,必须有更好的方法来做到这一点。总是有。谢谢你,如果这是愚蠢的或者已经被问过,我很抱歉。我找不到答案。

更新代码:

from random import randrange
from functools import partial

def foo1(arg_of_foo1):
    x = arg_of_foo1 + 1
    print "x is:", x

def foo2(arg1_of_foo2,arg2_of_foo2):
    y = arg1_of_foo2 + arg2_of_foo2
    print "y is:", y

def foo3():
    print "I don't need a parameter so I don't have one."

a = 0
b = 0

while b <= 100:
    print'='*20
    random_number = randrange(0,3)

    a += 1
    b += 10

    print "a is:", a
    print "b is:", b
    print "r_n is:", random_number

    print '-'*10
    raw_input("[Enter] to execute random function")

    list_of_foo = [partial(foo1,a), partial(foo2,a,b), partial(foo3)]

    list_of_foo[random_number]()

这段代码去掉了条件语句和不必要的参数。 谢谢督察!

对于未知数量的参数或未知类型的参数,只需执行 fn(*args)

您可以做三件事:

  1. 在函数定义中使用*args
  2. 重写您的函数以将列表(或元组或字典)作为唯一参数,并从中读取实际参数
  3. 使用ast读取函数签名,并为其提供正确数量的参数(暂时省略)

使用*args

在 python 中,您可以将 *args 定义为函数获取的参数列表,这会将参数序列分配给名为 args:[=32 的列表=]

In [113]: def func(*args):
   .....:     print "the arguments are:", ' '.join(args)
   .....:     

In [114]: func()
the arguments are:

In [115]: func('a')
the arguments are: a

In [116]: func('a', 'b')
the arguments are: a b

因此,考虑到这一点,您可以这样做:

def foo1(*args):
    param_of_foo1 = args[0]  # any other arguments will be discraded
    x = param_of_foo1 + 1
    print "x is:", x

def foo3(*uselessArgs):
    print "I have a parameter but I don't really need it..."

您仍然可以调用 foo3()foo3(1,2,3)


使用列表

这与之前的想法相同,但是您使用参数列表进行调用:

def foo1(L):
    param_of_foo1 = L[0]  # other entries will be ignored

这需要使用参数列表调用:foo1([1])foo1([1,2,3])

def foo1(arg):
    print "I got this as my argument:", arg

现在,foo1([1,2,3]) 将给出:

I got this as my argument: [1,2,3]

由于 arg 的行为与任何其他列表一样(就像 *args 的情况一样),您应该能够提取任意数量的参数(只要提供)。因此,由于您的函数需要的参数的最大数量是 1,因此始终提供至少一个参数的列表,并且任何额外的参数都将被忽略(尤其是 foo3

还有另一种方法,使用ast,但我认为这不是您所追求的,所以我暂时不考虑(评论,我会添加)


另一方面,如果您只打算用 4 调用 foo1,用 10 调用 foo2,那么这应该适合您:

>>> import functools
>>> import random
>>> def foo1(param_of_foo1):
...     x = param_of_foo1 + 1
...     print "x is:", x
... 
>>> def foo2(param_of_foo2):
...     y = param_of_foo2 + 2
...     print "y is:", y
... 
>>> def foo3(useless_param):
...     print "I have a parameter but I don't really need it..."
... 
>>> f = functools.partial(foo1, 4)
>>> f()
x is: 5
>>> list_of_foo = [functools.partial(foo1, 4), functools.partial(foo2, 10), functools.partial(foo3, 'discarded argument')]
>>> random.choice(list_of_foo)()
y is: 12
>>> random.choice(list_of_foo)()
x is: 5
>>> random.choice(list_of_foo)()
x is: 5
>>> random.choice(list_of_foo)()
x is: 5
>>> random.choice(list_of_foo)()
x is: 5
>>> random.choice(list_of_foo)()
x is: 5
>>> random.choice(list_of_foo)()
y is: 12
>>> random.choice(list_of_foo)()
x is: 5
>>> random.choice(list_of_foo)()
y is: 12
>>> random.choice(list_of_foo)()
I have a parameter but I don't really need it...
>>> random.choice(list_of_foo)()
x is: 5
>>> random.choice(list_of_foo)()
x is: 5
>>> random.choice(list_of_foo)()
x is: 5
>>>