使用for循环来定义多个函数 - Python

时间:2018-04-03 13:20:42

标签: python python-3.x functional-programming

假设我需要创建10个名为add1,add2,...,add10的函数。对于每个 i ,addi接受整数 x 并输出 x + i

当我尝试以下操作时,Python给了我一个NameError并评估了add2(10)。

for i in range(10):
    def addi(x):
        return x + (i+1)

我知道上面的代码是错误的,因为我定义的addi函数不是可变的;我很确定我所做的一切都是重新定义了10次。如何快速定义这10个功能?

5 个答案:

答案 0 :(得分:4)

在这种情况下,将functools.partial与词典结合使用。

我认为你 想要做的事情更复杂,因为这项特定任务不需要多个功能。

from functools import partial

def add(x, i):
    return x + i

d = {f'add{k}': partial(add, i=k) for k in range(1, 10)}

d['add3'](5)  # 8

<强>解释

  • 最好将可变数量的相关对象存储在专门定义的字典中。
  • functools.partial是一个高阶函数,它返回一个输入函数,其中选定的参数已修复。

答案 1 :(得分:4)

功能一般不可变;但他们可能会引用数据。在您的代码段中,此引用有点不清楚,但i仅在函数体中出现一次,作为读取。因此,它从一些外部范围读取,通常是包含在其中的for循环的函数或模块。由于这恰好是共享上下文,因此每个addi函数最终都会使用相同的i

另一个问题是,您在每次迭代时都使用名称addi,并且该函数永远不会出现在另一个名称下。因此,先前定义的任何addi函数都会丢失。这引出了第三个问题;为什么要动态创建名称(如函数名称)?使用集合几乎总是更好,例如jpp的答案中的d字典。否则,什么代码甚至会引用您创建的函数?

所有这一切,仍然可以做你所要求的,虽然很奇怪。这是一种方式:

def addfunc(n):
    def addn(x):
        return x+n
    return addn

for i in range(1,10):
    globals()['add{}'.format(i)] = addfunc(i)

这会滥用globals将动态创建的名称注入模块的命名空间,并将这些函数中的每一个嵌套到另一个函数中,以创建包含其各自n值的名称空间。另一个经典黑客是使用默认参数,而partial applicationoperator.add是一个更整洁的功能风格。

答案 2 :(得分:2)

解决方案:

from types import FunctionType
from copy import copy

def copy_function(fn, name):
    return FunctionType(
    copy(fn.func_code),
    copy(fn.func_globals),
    name=name,
    argdefs=copy(fn.func_defaults),
    closure=copy(fn.func_closure)
)

for i in range(10):
    name = 'add' + str(i)
    def _add(x):
        return x + (i+1)
    globals()[name] = copy_function(_add, name)


print add1(2) # 4
print add3(8) # 12 

使用https://stackoverflow.com/a/34796018/7529716

中的复制功能

答案 3 :(得分:1)

这有帮助吗?

def createFunc(i):
  def func(x):
    return x + (i+1)
  return func

然后只需创建函数并将它们存储在数组中:

add = [createFunc(i) for i in range(10)]
print add[0](1)  # 1+(0+1) = 2
print add[0](2)  # 2+(0+1) = 3
print add[2](10) # 10+(2+1) = 13
print add[2](11) # 11+(2+1) = 14

答案 4 :(得分:1)

正如其他人所说,如果你应该在生产代码中这样做,那就有问题了。但是,出于教育目的,这里是如何通过生成函数名称并将它们注入全局名称空间来实现的:

>>> def f(x, i):
...     return x + i + 1
... 
>>> from functools import partial
>>> for i in range(10):
...     globals()['add%s' % i] = partial(f, i=i)
... 
>>> add8(5)
14
>>> add3(5)
9

functools.partial在Python中实现currying来创建单个函数定义的副本,其中每个副本都包含#34;硬编码&#34;一个或多个函数参数。