2017-07-26 115 views
4

如果我创建一个装饰像以下:为什么我们需要装饰器中的包装函数?

def my_decorator(some_fun): 
    def wrapper(): 
     print("before some_function() is called.") 
     some_fun() 
     print("after some_function() is called.") 
    return wrapper 

@my_decorator 
def just_some_function(): 
    print("Wheee!") 

另一种装饰,可以定义为:

def my_decorator(some_fun): 
    print("before some_function() is called.") 
    some_fun() 
    print("after some_function() is called.") 

@my_decorator 
def just_some_fun(): 
    print("some fun") 

装饰都将工作一样。在装饰器中使用“包装器”功能有什么好处。我没有达到目的。

+3

你尝试过吗?这两个代码块对我来说产生完全不同的结果。 – RishiG

+0

真的吗?你有没有尝试在你的第二代码块中调用'just_some_fun()'?是的,当'my_decorator'在'just_some_fun'上被调用,但是当_call_'just_some_fun()'它与'TypeError:'NoneType'对象不可调用'崩溃时,东西被打印出来。 –

+1

“两个装饰者都会一样” - 你有没有支持这个说法? – user2357112

回答

1

具有包装函数的目的是函数装饰器接收一个函数对象进行装饰,并且它必须返回装饰函数必须

您的第二版my_decorator没有明确的return声明,因此它返回None。当my_decorator经由@修饰语法称为

before some_function() is called. 
some fun 
after some_function() is called. 

获取打印,然后None获取分配给该名称just_some_fun。因此,如果您将print(just_some_fun)添加到该代码的末尾,它将打印None。使用正常功能

可能更容易理解发生了什么事情,如果我们摆脱@语法糖和重新编写代码调用语法:

def my_decorator(some_fun): 
    print("before some_function() is called.") 
    some_fun() 
    print("after some_function() is called.") 

def just_some_fun(): 
    print("some fun") 

just_some_fun = my_decorator(just_some_fun) 
0

在Python的装饰器是可调用的对象,其在最简单的情况是取一个参数作为一些函数或类的函数。装饰器应该再次返回它需要的相同类型(所以如果它需要函数它应该返回函数)。关键在于装饰器被调用的时候。

当您导入Python文件或直接运行它时,Python解释器会浏览内容并收集有关定义了哪些类和函数的信息,并且如果它遇到某些代码(而不是声明),它将执行它。

如果解释器在装饰器上遇到装饰函数,则调用装饰器并用装饰器中的返回值替换装饰后的函数。

比方说,你有这样的代码:

@my_decorator 
def my_function() 
    print("My_function") 

这相当于这一号召:

def my_function() 
    print("My_function")  

my_function = my_decorator(my_function) 

如果装饰会是这样一个

def my_decorator(func): 
    print("decorated) 
    return 42 

那么my_function是甚至没有一个函数,它会是一个整数(你可以尝试print(my_function)

所以,当你定义装饰器为

def my_decorator2(some_fun): 
    print("before") 
    some_fun() 
    print("after") 

那么这个装饰没有返回值(在Python这意味着它返回None)。

@my_decorator2 
def decorated(): 
    print("inside") 

打印

before 
inside 
after 

但调用decorated()将引发异常'NoneType' object is not callable因为decoratedNone取代。

你应该总是创建一个装饰器,它返回类似于函数或类的东西(通常是里面的“包装”函数)。有时可以从装饰器返回其他函数/类,但它通常会混淆代码并将其转换为完全不可维护的代码。

相关问题