【问题标题】:Python Dispatcher Definitions in a Function [duplicate]函数中的Python调度程序定义[重复]
【发布时间】:2015-06-15 00:22:36
【问题描述】:

每次向调度程序添加新函数时,我都会遇到 Python 调度程序定义更改的问题。一个例子:

def dispatcher_create():
    dispatcher = {}
    for i in range(5):
        def square():
            return i**2
        dispatcher[i] = square
    for j in range(5):
        print dispatcher[j]()
    return dispatcher

此代码将值16 打印五次。我希望它会打印出0 1 4 9 16。我确定我每次都重新定义 square 是个问题,但我不确定如何最好地解决它。

【问题讨论】:

标签: python


【解决方案1】:

return i**2 中的i 绑定到名称 i,而不是 i

试试这个创建一个新变量,绑定到适当的值:

def dispatcher_create():
    dispatcher = {}
    for i in range(5):
        def square(i=i):
            return i**2
        dispatcher[i] = square
    for j in range(5):
        print dispatcher[j]()
    return dispatcher

dispatcher_create()

【讨论】:

    【解决方案2】:

    不,每次重新定义square() 就是做你想做的事,你可以通过打印dispatcher 的内容来检查:其中的所有函数都将根据需要具有不同的ID。

    问题在于您正在创建一个closure,因此当您调用存储在dispatcher 中的任何函数时,它们正在访问i 的最新值,而不是使用i 时的值它们被定义了。

    Robᵩ 展示了一种解决方法,将i 作为参数传递给square();这是另一种方式:使用 another 闭包,该闭包将 i 作为 arg,因此它可以保留它以用于其生成的平方函数。

    def dispatcher_create():
        dispatcher = {}
        def make_square(j):
            def square():
                return j**2
            return square
    
        for i in range(5):
            dispatcher[i] = make_square(i)
        return dispatcher
    
    dd = dispatcher_create()
    print dd
    
    for j in range(5):
        print dd[j]()
    

    典型输出

    {0: <function square at 0xb73a0a3c>, 1: <function square at 0xb73a0dbc>, 2: <function square at 0xb73a0d84>, 3: <function square at 0xb73a5534>, 4: <function square at 0xb73a517c>}
    0
    1
    4
    9
    16
    

    Robᵩ 的版本稍微简单一些,但这个版本的优点是dispatcher 中的函数具有所需的参数签名,即它们不带参数,而 Robᵩ 的函数只带一个默认值的参数,你可以超车。

    FWIW,您可以使用i 而不是j 作为make_square() 的参数,因为它只是make_square() 的局部变量。 OTOH,使用i 会在外部范围内遮盖i,我觉得使用j 会稍微不那么混乱。

    【讨论】:

      【解决方案3】:

      我认为这与范围有关。 i 变量在使用它的 for 循环之后保持定义。如果在 for 循环之后打印 i 的值,您会看到它是 4。如果然后在下一个 for 循环中调用函数,则 i 的值是在当前范围内使用。

      至于解决方案,我认为 functools.partial 会是一个不错的选择。

      from functools import partial
      
      def dispatcher_create():
          dispatcher = {}
          for i in range(5):
              def square(value):
                  return value**2
              dispatcher[i] = partial(square, i)
          for j in range(5):
              print dispatcher[j]()
          return dispatcher
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-01-09
        • 2021-07-20
        • 2015-09-06
        • 1970-01-01
        • 2021-01-11
        • 2019-01-16
        • 1970-01-01
        相关资源
        最近更新 更多