简体   繁体   English

没有包装器的装饰器与函数 - Python

[英]Decorator vs Function without wrapper - Python

I am currently trying to understand what decorators are and what they are used for.我目前正在尝试了解什么是装饰器以及它们的用途。 Until now, I've learned that they are just functions which pass and return functions as arguments and their purpose is to modify a function w/o modifying the original function.到目前为止,我已经了解到它们只是将函数作为参数传递和返回的函数,它们的目的是修改函数而不修改原始函数。

My question is related to the classic structure used to define them.我的问题与用于定义它们的经典结构有关。 Usually you define a decorator function and within it, another function called wrapper which is returned by the decorator function.通常你定义一个装饰器函数,并在其中定义另一个称为包装器的函数,它由装饰器函数返回。

So my question is, why is wrapper created inside the decorator when it could be done with just a function?所以我的问题是,为什么在装饰器内部创建包装器,而它可以只用一个函数来完成? Would`t it be more "pythonic" to reduce code side by doing so?通过这样做来减少代码方面会不会更“pythonic”?

As an example, the following 2 pieces of code:例如,以下2段代码:

def country(func):
    def wrapper_function():
        print("The name of my favorite country is: ")
        return func()
    return wrapper_function

@country # == fav_country = country(fav)
def fav():
    print("Sweden")

fav()

OUTPUT:输出:

The name of my favorite country is:我最喜欢的国家的名字是:

Sweden瑞典

def country(func):
    print("The name of my favorite country is: ")
    return func

@country # == fav_country = country(fav)
def fav():
    print("Sweden")

fav()

OUTPUT: The name of my favorite country is:输出:我最喜欢的国家的名字是:

Sweden瑞典

You are correct that a decorator is nothing else then a function taking a function as an argument and returning a function.你是对的,装饰器就是一个将函数作为参数并返回一个函数的函数。 But these two:但是这两个:

def country1(func):
    def wrapper_function():
        print("The name of my favorite country is: ")
        return func()
    return wrapper_function

def country2(func):
    print("The name of my favorite country is: ")
    return func

are not equivalent.不等价。 Consider考虑

@country1
def fav1():
    print("Sweden")

@country2
def fav2():
    print("Sweden")

and see what happens when you call看看当你打电话时会发生什么

fav1()
fav1()
fav1()

and

fav2()
fav2()
fav2()

Your country2 doesn't modify the original function and the result is The name of my favorite country is: printed only once during decoration process (at function declaration).你的country2没有修改原来的函数,结果是The name of my favorite country is:在装饰过程中只打印一次(在函数声明时)。 While country1 changes the behaviour of the decorated function, you will see the message three times.虽然country1更改了装饰函数的行为,但您将看到该消息三遍。

In your case a wrapper function isn't needed.在您的情况下,不需要包装函数。 You aren't doing anything with the passed parameters and the return parameters.您没有对传递的参数和返回参数做任何事情。

def printall(func):
    def inner(*args):
        print('Arguments for args: {}'.format(args))
        return func(*args)
    return inner

@printall
def random_func(*args):
    return sum(*args)

a = random_func(2, 2)

It is useful if for instance you want the passed parameters to start with a higher value (sort of like an added offset).例如,如果您希望传递的参数以更高的值开始(有点像添加的偏移量),这很有用。 Then you could do:那么你可以这样做:

def offset(func):
    def inner(*args):
        args = [arg + 2 for arg in args]
        return func(*args) # <-- here it is calling your random_func with modified passed parameters!
    return inner

@offset
def random_func(*args):
    return sum(*args)

a = random_func(2, 2)

So when modifying the passed parameters you have to use a wrapper to achieve this.因此,在修改传递的参数时,您必须使用包装器来实现这一点。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM