简体   繁体   English

在python装饰器中foo = bar(foo)和something = bar(foo)之间有什么区别?

[英]what is difference between foo=bar(foo) and something=bar(foo) in decorator in python?

I read about we can create reference of any function in python but i also read that while creating a decorator we use a special syntax called "@" : ex: @decorator_function and this @decorator_function is equal to new_function=decorator_function(new_function) 我读到我们可以在python中创建任何函数的引用,但同时我也读到在创建装饰器时,我们使用一种特殊的语法,称为“ @”:例如:@decorator_function,此@decorator_function等于new_function=decorator_function(new_function)

so my doubt is in my view both : 所以我都怀疑:

  1. anything = decorator_function(new_function)
  2. new_function=decorator_function(new_function)

both are playing the role of closure but both result different output. 两者都扮演着封闭的角色,但是两者都导致了不同的输出。 so what is big difference between both of them? 那么两者之间的最大区别是什么?

example code : 示例代码:

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)

The original something function you wrote makes a recursive call to something , not a . 您编写的原始的something函数递归调用something ,而不是a

If you assign deco(something) to a , then something is still the original function, and the recursive call will call the original function: 如果分配deco(something)a ,然后something仍然是原来的功能,以及递归调用将调用原始的功能:

  • new function calls original function 新功能调用原始功能
  • original function looks up something , finds original function 原始功能查找something ,找到原始功能
  • original function calls original function... 原始函数调用原始函数...

If you assign deco(something) to something , then something is now the new function, and the recursive call will call the new function: 如果将deco(something)分配给something ,则something现在是新函数,并且递归调用将调用新函数:

  • new function calls original function 新功能调用原始功能
  • original function looks up something , finds new function 原始功能查找something ,找到新功能
  • original function calls new function 原始函数调用新函数
  • new function calls original function... 新功能调用原始功能...

For the first one, a = deco(something) 对于第一个, a = deco(something)

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

The second one, something = deco(something) is just the same except your original function something now has become the wrapper function that deco returned. 第二个, something = deco(something)就是除了你的原始功能相同something ,现在已经成为wrapper该功能deco返回。

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

Both something and a wrap the original something before it was overridden by something = deco(something) assignment. 这两个somethinga 包装something之前,它是由覆盖something = deco(something)分配。 Python internally stored the original something function somewhere in the wrapper functions: Python内部将原始的something函数存储在包装函数中的某个位置:

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

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

In the last assignment something has become something different: 在上一次作业中, something变得与众不同:

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

Both of your assignments using manual calls to the decorator work. 您使用手动调用装饰器的两个工作。 But one of them (the one that rebinds something ) replaces the original function so that it can't be reached by its original name any more. 但是其中之一(重新绑定something )替换了原来的函数,因此不再可以通过其原始名称来访问它。 It's not any different than using any other assignment. 与使用任何其他分配没有什么不同。 For instance: 例如:

def foo(x):
    return x + 1

a = 10

a = foo(a)

When you assign the result of foo(a) to a , it replaces the old value of 10 with a new value 11 . foo(a)的结果分配给a ,它将旧值10替换为新值11 You can't get the 10 any more. 您再也无法获得10了。

Decorator syntax does the same thing. 装饰器语法执行相同的操作。

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

It's not forbidden to use a decorator to create a differently named function, it's just not normally as useful (and so there's no special syntax for it): 禁止使用装饰器创建一个命名不同的函数,通常它没有那么有用(因此没有特殊的语法):

def func_3(x):
    pass

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 foo.bar()和bar(foo)之间的区别? - Difference between foo.bar() and bar(foo)? 在 python 中,“import foo.bar as bar”和“from foo import bar”有什么区别? - In python, what is the difference between 'import foo.bar as bar' and 'from foo import bar'? 在 Python 中理解 [foo for bar, foo in arr] - Understanding [foo for bar, foo in arr] in Python foo = list,foo = []和foo = list()之间的区别? - Difference between foo=list, foo=[], and foo=list()? Django / Python:/ foo / bar中的ValueError - Django/Python: ValueError at /foo/bar isinstance(foo,bar) vs type(foo) is bar - isinstance(foo,bar) vs type(foo) is bar 使用属性装饰器后,python object 有两个非常相似的属性(foo.bar 和 foo._bar)。 那样行吗? - After using property decorator, python object has two very similar attributes (foo.bar and foo._bar). Is that ok? xpath //*[.="Foo"] 和 xpath //*["Foo"] 在谓词中只有一个字符串有什么区别? - What is the difference between the xpath //*[.="Foo"] and the xpath //*["Foo"] with only a string in the predicate? 什么是Python相当于或等于表达式,以获得返回foo或foo =&#39;bar&#39;的工作原理? - What's Python equivalent to or equals expression, to get return foo or foo = 'bar' working? if(foo或bar或baz)为None: - if (foo or bar or baz) is None:
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM