【问题标题】:Curious as to what the interpreter is doing here好奇口译员在这里做什么
【发布时间】:2019-02-14 06:35:22
【问题描述】:

我正在学习装饰器设计模式教程 (感谢 Jungwoo Ryoo)

我很好奇为什么我可以换行:return decoratorprint(hello_world())return decorator()print(hello_world)

from functools import wraps

def make_blink(function):
    """Defines the decorator"""

    @wraps(function)
    # Define the inner function
    def decorator():

        # Grab the return value of the function being decorated
        ret = function()
        # Add new functionality to the function being decorated
        return "<blink>"+ ret + "<b/link>"
    return decorator #return decorator()#<THIS LINE HERE SWAPPED

# Apply the decorator here!
@make_blink
def hello_world():
    """Original function! """

    return "Hello, World!"

# Check the result of decorating
print(hello_world()) #print(hello_world) #<THIS LINE HERE SWAPPED

口译员不是每次都在做不同的事情吗?我只是在寻找一些见解,以便更好地了解正在发生的事情

【问题讨论】:

    标签: python python-3.x python-decorators


    【解决方案1】:

    装饰器实际上只是函数,而函数只是对象。

    线条

    @make_blink
    def hello_world():
        # ...
    

    基本相同

    def hello_world():
        # ...
    hello_world = make_blink(hello_world)
    

    除了函数对象从不首先分配给hello_world(它在堆栈上以传递给装饰器)。

    所以无论你从make_blink()返回什么都会分配回hello_world。这可以是一个函数对象,但也可以是完全不同的东西。

    所以当你使用return decorator 时,你告诉Python 将hello_world 设置为嵌套的函数对象。当你使用return decorator() 时,你告诉Python 使用decorator() 函数的结果。在这里,这是一个字符串值。就好像你这样做了:

    def hello_world():
        """Original function! """
        return "Hello, World!"
    
    hello_world = "<blink>" + hello_world() + "</blink>"
    

    对于这个特定的示例来说这很好,因为hello_world() 函数的主体只返回每次都相同的字符串

    但是,如果您更改原始的 hello_world() 函数体以在每次调用它时返回不同的东西怎么办?如果你有:

    import random
    
    @make_blink
    def random_greeting():
        return 'Hello ' + random.choice('DonAr', 'Martijn Pieters', 'Guido van Rossum') + '!'
    

    现在,您从make_blink() 调用返回的结果很大!对于顶级模块,装饰器在导入时只执行一次。如果您使用了return decorator(),您将只运行一次random.choice(),并且您将random_greeting 的值固定为单个静态字符串结果。

    一般来说,装饰器应该再次返回一个可调用对象。这可以是原始函数(装饰器只是更新某种注册),包装函数(在调用原始函数之前或之后做额外的事情),甚至是完全不同的东西。但这并不是一成不变的,口译员也不在乎。

    装饰器只是在您的程序中使用的可重复使用的东西,一种工具。如果您对返回原始函数结果的装饰器有特定用途,那么您可以随意这样做。

    【讨论】:

    • 感谢您添加 random_greeting() 部分。它以如此清晰的方式说明了您何时想要使用 return decorator() 与 return decorator 的动机。
    猜你喜欢
    • 1970-01-01
    • 2011-01-28
    • 2012-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多