如果我创建一个类似于下面的装饰器:
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")
两个装饰器都会一样。使用"包装"有什么好处?装饰里面的功能。我没有达到目的。
答案 0 :(得分:3)
具有包装函数的目的是函数装饰器接收要装饰的函数对象,并且必须返回装饰函数。
您的第二版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)
答案 1 :(得分:1)
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
,因为decorated
已替换为None
。
你应该总是创建一个返回一些有用功能的装饰器,比如函数或类(通常是里面的“wrap”函数)。有时从装饰器返回其他东西然后函数/类是有用的,但它通常会混淆你的代码并将其转换为完全不可维护的东西。
答案 2 :(得分:0)
它已经解释了为什么我出于好奇而使用包装器功能 举例说明了如果不需要包装函数怎么办。
None
或pass
def decorator_func(to_be_decorated_function):
print("Logging IN: Currrently in function")
to_be_decorated_function()
print("Logging OUT: Currrently in function")
def a(): None # or def a(): pass
return (a)
@decorator_func
def to_be_decorated_function():
print('October 16, 2000')
to_be_decorated_function()
# equivalent to
#to_be_decorated_function = decorator_func(to_be_decorated_function)
def decorator_func(to_be_decorated_function):
print("Logging IN: Currrently in function")
to_be_decorated_function()
print("Logging OUT: Currrently in function")
@decorator_func
def to_be_decorated_function():
print('October 16, 2000')
to_be_decorated_function # notice I'm just using the object and not callable function
# equivalent to
#decorator_func(to_be_decorated_function)
Logging IN: Currrently in function
October 16, 2000
Logging OUT: Currrently in function