面试题答案
一键面试- 装饰器顺序影响结果的原理:
- 装饰器本质上是函数,当多个装饰器应用于一个函数(或类的方法)时,它们的顺序是从内到外执行的。也就是说,离被装饰函数最近的装饰器最先执行,然后依次向外。
- 每个装饰器都会对原函数进行一定的修改或增强,后续的装饰器是基于前一个装饰器修改后的函数进行操作的,所以装饰器的顺序不同,最终对原函数的修改结果也会不同。
- 代码示例:
def decorator1(func):
def wrapper(*args, **kwargs):
print("Decorator 1 before")
result = func(*args, **kwargs)
print("Decorator 1 after")
return result
return wrapper
def decorator2(func):
def wrapper(*args, **kwargs):
print("Decorator 2 before")
result = func(*args, **kwargs)
print("Decorator 2 after")
return result
return wrapper
def decorator3(func):
def wrapper(*args, **kwargs):
print("Decorator 3 before")
result = func(*args, **kwargs)
print("Decorator 3 after")
return result
return wrapper
class MyClass:
@decorator1
@decorator2
@decorator3
def my_method(self):
print("Inside my_method")
my_obj = MyClass()
my_obj.my_method()
- 输出结果:
Decorator 1 before
Decorator 2 before
Decorator 3 before
Inside my_method
Decorator 3 after
Decorator 2 after
Decorator 1 after
-
解释:在这个例子中,
@decorator3
离my_method
最近,所以它最先对my_method
进行装饰。当调用my_obj.my_method()
时,实际上调用的是decorator1
装饰后的函数,而decorator1
装饰后的函数又包含了decorator2
装饰后的函数,decorator2
装饰后的函数又包含了decorator3
装饰后的函数。所以先打印出Decorator 1 before
,然后进入decorator2
的wrapper
打印Decorator 2 before
,再进入decorator3
的wrapper
打印Decorator 3 before
,接着执行原my_method
打印Inside my_method
,之后从decorator3
的wrapper
开始返回,依次打印Decorator 3 after
,Decorator 2 after
,Decorator 1 after
。 -
如果改变装饰器顺序:
class MyClass2:
@decorator3
@decorator2
@decorator1
def my_method(self):
print("Inside my_method")
my_obj2 = MyClass2()
my_obj2.my_method()
- 输出结果:
Decorator 3 before
Decorator 2 before
Decorator 1 before
Inside my_method
Decorator 1 after
Decorator 2 after
Decorator 3 after
- 解释:此时
@decorator1
离my_method
最近,所以它最先对my_method
进行装饰。调用my_obj2.my_method()
时,执行顺序和之前不同,先打印Decorator 3 before
,再进入decorator2
的wrapper
打印Decorator 2 before
,接着进入decorator1
的wrapper
打印Decorator 1 before
,执行原my_method
打印Inside my_method
,然后从decorator1
的wrapper
开始返回,依次打印Decorator 1 after
,Decorator 2 after
,Decorator 3 after
。
综上所述,装饰器的顺序不同,对原函数(或类的方法)的增强和修改顺序也不同,导致最终的行为和输出结果不同。