代码之家  ›  专栏  ›  技术社区  ›  user8224771

python中decorator中的foo=bar(foo)和something=bar(foo)有什么区别?

  •  1
  • user8224771  · 技术社区  · 7 年前

    我读过关于我们可以在python中创建任何函数的引用的文章,但我也读到在创建decorator时,我们使用了一种称为“@”的特殊语法:例如:@decorator\u函数 @decorator_function 等于 new_function=decorator_function(new_function)

    因此,在我看来,我对以下两个方面都持怀疑态度:

    1. anything = decorator_function(new_function)
    2. new_函数=decorator_函数(new_函数)

    两者都扮演着闭包的角色,但都会产生不同的输出。那么,它们之间有什么大的区别呢?

    示例代码:

    def deco(fn):
        def wrapper(*args):
            print('called')
            return fn(*args)
    
        return wrapper
    
    
    def something(x):
        if x == 0:
            print('first')
            something(x+1)
        else:
            print('hello')
    
    
    print('new name')
    a = deco(something)
    a(0)
    print('\nreassigning to the same name')
    something = deco(something)
    something(0)
    
    3 回复  |  直到 7 年前
        1
  •  4
  •   user2357112    7 年前

    原件 something 您编写的函数递归调用 a

    如果您分配 deco(something) 然后 仍然是原始函数,递归调用将调用原始函数:

    • 新函数调用原始函数
    • ,查找原始函数

    如果您分配 装饰(某物) 然后 某物 现在是新函数,递归调用将调用新函数:

    • 新函数调用原始函数
    • 某物
    • 新函数调用原始函数。。。
        2
  •  1
  •   GIZ    7 年前

    a = deco(something)

    def deco(fn):
        def wrapper(*args):
            print('called') 
            return something(*args)      # Notice here
    return wrapper 
    

    第二个, something = deco(something) 都是一样的 您的原始功能 something 现在已经成为 wrapper 功能: deco

    >>> something
    <function deco.<locals>.wrapper at 0x7fbae4622f28>
    >>> a
    <function deco.<locals>.wrapper at 0x7fbae4622ea0>
    

    某物 a 起初的 某物 某物=装饰(某物)

    >>> something.__closure__[0].cell_contents
    <function something at 0x7fbae4622bf8>
    
    >>> a.__closure__[0].cell_contents
    <function something at 0x7fbae4622bf8>
    

    在上次作业中 某物

    >>> something
    <function deco.<locals>.wrapper at 0x7fbae4622f28>
    
        3
  •  0
  •   Blckknght    7 年前

    你的两个作业都是通过手动调用装饰器来完成的。但是其中一个(重新绑定的 something )替换原始函数,使其无法再通过其原始名称访问。这与使用任何其他作业没有什么不同。例如:

    def foo(x):
        return x + 1
    
    a = 10
    
    a = foo(a)
    

    当您指定 foo(a) a ,它取代了 10 具有新值 11 . 你不能得到

    Decorator语法也做同样的事情。

    def deco(fn):
        def wrapper(*args):
            print('called')
            return fn(*args)
    
        return wrapper
    
    def func_1(x):
        pass
    func_1 = deco(func_1) # replace the old func_1 with a decorated version
    
    @deco                 # the @ syntax does the same thing!
    def func_2(x):
        pass
    

    def func_3(x):
        pass
    
    func_4 = deco(func_3) # this works, creating a new function name without hiding the old one