【问题标题】:How to define a function inside a loop [duplicate]如何在循环内定义函数[重复]
【发布时间】:2017-06-06 08:53:50
【问题描述】:

为什么这不起作用?

u = {}
for me in ['foo', 'bar']:
   def callback():
       return 'I am %s' % me
   u[me] = callback

我得到的输出是:

>>> u['foo']()
'I am bar'

似乎callback 在最近一次迭代中定义了一次。

编辑

正如 kawadhiya21 所提议的,类方法会起作用:

class CallbackFactory():
    def __init__(self, me):
       self.me = me

    def __call__(self):
       return 'I am %s' % self.me

u = {}
for me in ['foo', 'bar']:

   u[me] = CallbackFactory(me)

但它比前一种方法复杂得多。

【问题讨论】:

  • 试试u[me] = callback()?
  • 尝试在for循环外定义CallBack并从for循环内调用函数
  • 你觉得 types.FunctionType 能帮到你吗?
  • 你确实不需要需要创建一个类。只需了解 Python 闭包在词法范围内具有后期绑定行为。

标签: python function-pointers


【解决方案1】:

所有函数都引用同一个变量me。当您尝试调用该函数时,me 的值是 'bar',因为这就是循环结束时的值。

如果您希望 me 为函数的每个定义采用不同的值,则每个函数都需要自己的变量副本。

u = {}
for me in ['foo', 'bar']:
   def callback(me_copy=me):
       return 'I am %s' % me_copy
   u[me] = callback

如果您愿意,可以将其缩短为:

u = {}
for me in ['foo', 'bar']:
   u[me] = lambda me_copy=me: 'I am %s'%me_copy

甚至

u = { me: (lambda me_copy=me: 'I am %s'%me_copy) for me in ('foo', 'bar') }

【讨论】:

    【解决方案2】:

    首先,在您的示例中,u['foo'] 根本不应该返回一个字符串,而是一个函数句柄。 :) 编辑:这句话不再相关。

    其次,您的函数callback 使用外部范围的me。如果您在外部范围内更改此值(在您的情况下通过循环),则函数的输出也会更改。

    要解决此问题,您需要将 me 设为函数自身范围的一部分,例如通过这样做:

    def callback(int_me=me):
        return 'I am %s' % int_me
    

    【讨论】:

    • 我的错误,我忘记了示例中的()
    【解决方案3】:

    您想定义一系列回调,而不是简单地保存一堆输出,对吧?定义一个绑定你想要的参数的函数,像这样:

    def make_callback(param):
        def callback():
           return 'I am %s' % param
        return callback
    
    for me in ['foo', 'bar']:
        u[me] = make_callback(me)
    
    >>> u["foo"]()
    'I am foo'
    

    【讨论】:

      【解决方案4】:

      您每次都在循环中重新定义回调()。所以最新版本可以工作。我认为你应该使用基于类的方法。

      【讨论】:

      • 这是不正确的。 u['foo']u['bar'] 不会是同一个函数句柄。
      猜你喜欢
      • 2019-01-28
      • 1970-01-01
      • 1970-01-01
      • 2021-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-17
      相关资源
      最近更新 更多