Python 是否有更好的方法根据函数的输入在函数中选择不同的操作?
我制作了一个通用函数来生成大小为x,y的二维网格,Python 是否有更好的方法根据函数的输入在函数中选择不同的操作?,python,performance,readability,Python,Performance,Readability,我制作了一个通用函数来生成大小为x,y的二维网格,make_grid def make_grid(x, y, mode="empty"): if mode == "rand": def filling(): return randint(0, 1) else: def filling(): return 0 grid = [] for r in range(x): ro
make_grid
def make_grid(x, y, mode="empty"):
if mode == "rand":
def filling():
return randint(0, 1)
else:
def filling():
return 0
grid = []
for r in range(x):
row = []
for c in range(y):
row.append(filling())
grid.append(row)
return grid
我已经将其设置为基于输入模式定义填充函数,这样,如果在for循环中不必要地检查s,我就不会运行一堆——希望在大网格上这样可以节省大量时间
然而,我不确定这是否是实现这一点的最具Python风格的方式——以这种方式在函数中定义函数感觉不干净。有人能提出更好(更清晰或更有效)的方法吗?我觉得lambdas可能是正确的方式,但我从来没有真正适应过他们。。。我至少应该能够在其他地方定义函数,选择在for循环之前调用哪个函数,然后在for循环期间使用它,对吗
编辑:这里有一个更简单的例子,因为我一开始是可耻的懒惰,没有费心做一个合适的。。。(我保留原稿,以便答案仍然有意义。)
试想一下,有条件地定义的action\u to_take
函数足够复杂,足以证明这个问题,并且循环次数足够多,使得对代码性能的质疑变得合理。像这样有条件地定义函数是不常见的。您可以使用更直接的方法简化此过程并将其缩短很多:
import numpy as np
def make_grid(x, y, mode='empty'):
if mode == 'rand':
return np.random.randint(0, high=2, size=(y, x)).tolist()
return np.zeros((y, x)).tolist()
如果您不喜欢numpy,我会使用列表理解,因为它使代码简洁:
from random import randint
def grid(x=1, y=1, zeros=False):
return [[0 if zeros else randint(0,1) for _ in range(y)] for _ in range(x)]
a = grid(x=7, y=10, zeros=False)
但是,很难概括太多超出此范围的内容。一般来说,有条件地定义函数是很少见的。在函数中有条件地定义一个值更为常见(有关示例,请参阅上面mygrid()
函数中的x if b else y语法)
如果您发布了您的实际情况,或者关于您有条件地想要实例化的函数的更多信息,我们可能会提供更多信息。无论哪种方式,如果您需要支持这两种行为,通常在条件外定义这些函数是有意义的,但在条件内调用它们是有意义的,就像@kederrac所做的那样…像这样有条件地定义函数是不常见的。您可以使用更直接的方法简化此过程并将其缩短很多:
import numpy as np
def make_grid(x, y, mode='empty'):
if mode == 'rand':
return np.random.randint(0, high=2, size=(y, x)).tolist()
return np.zeros((y, x)).tolist()
如果您不喜欢numpy,我会使用列表理解,因为它使代码简洁:
from random import randint
def grid(x=1, y=1, zeros=False):
return [[0 if zeros else randint(0,1) for _ in range(y)] for _ in range(x)]
a = grid(x=7, y=10, zeros=False)
但是,很难概括太多超出此范围的内容。一般来说,有条件地定义函数是很少见的。在函数中有条件地定义一个值更为常见(有关示例,请参阅上面mygrid()
函数中的x if b else y语法)
如果您发布了您的实际情况,或者关于您有条件地想要实例化的函数的更多信息,我们可能会提供更多信息。无论哪种方式,如果您需要支持这两种行为,通常在条件外定义这些函数是有意义的,但在条件内调用它们是@kederrac所做的…您可以使用dict:
def fill_rand():
return randint(0, 1)
def default_fill():
return 0
# you can add how many modes you want
filling_mode = {
'rand': fill_rand,
}
def make_grid(x, y, mode="empty"):
filling = filling_mode.get(mode) or default_fill
grid = []
for r in range(x):
row = []
for c in range(y):
row.append(filling())
grid.append(row)
return grid
您可以使用dict:
def fill_rand():
return randint(0, 1)
def default_fill():
return 0
# you can add how many modes you want
filling_mode = {
'rand': fill_rand,
}
def make_grid(x, y, mode="empty"):
filling = filling_mode.get(mode) or default_fill
grid = []
for r in range(x):
row = []
for c in range(y):
row.append(filling())
grid.append(row)
return grid
如果mode参数仅用于确定在函数中的某个点要执行的操作,那么我刚才想到的另一个选项就是将函数名作为参数传递。详情如下:
def action_one():
print("mode1")
def action_default():
print("other")
def example(func=lambda *args: None):
for r in range(1000):
for c in range(1000):
func()
然后可以调用example(action\u default)
或example(action\u one)
,并将lambda表达式作为默认值,甚至example()
-在调用func
时,它将不起任何作用。如果mode参数仅用于确定在函数中的某个点要执行的操作,我刚才想到的另一个选项是将函数名作为参数传递。详情如下:
def action_one():
print("mode1")
def action_default():
print("other")
def example(func=lambda *args: None):
for r in range(1000):
for c in range(1000):
func()
然后,您可以调用example(action\u default)
或example(action\u one)
,将lambda表达式作为默认值,甚至example()
——这在调用func
时不会起任何作用。像这样有条件地定义函数是很少见的。为什么不使用row.append(x)
,其中x只是在前一行有条件地定义的?@duhaime是的,我认为有条件地定义函数会非常不正常。有条件地定义我在前一行中附加的内容的问题是,条件将被计算x*y次,即使每次都必须得出相同的结论,这是我的懒惰。添加了更简单的示例。像这样有条件地定义函数是很少见的。为什么不使用row.append(x)
,其中x只是在前一行有条件地定义的?@duhaime是的,我认为有条件地定义函数会非常不正常。有条件地定义我在前一行中附加的内容的问题是,条件将被计算x*y次,即使每次都必须得出相同的结论,这是我的懒惰。添加了更简单的示例。谢谢@duhaime,我不知道numpy的randint有一个大小参数。在我的示例中,了解并明确避免不必要的循环条件非常有用!不过,对于一般类型的问题,如果能有一个答案就太好了。如果在本例中不存在numpy,我将不得不编写自己的numpy.random.randint
和numpy.zero
,这将涉及到两者之间相当多的重复工作。我是否可以说,这将我试图为其他函数找到最干净的解决方案的问题委托给了其他函数?@JRVeale我在我的回答中添加了一点,以表明您可以通过列表理解非常轻松、简洁地复制numpy所需的行为。这种风格对您来说可能太简洁了,但当代码库达到数万行时,保持这种风格会很有帮助