python普通装饰器为什么能够给方法装饰,定义成类的话必须要定义__get__
最近在看PythonCookBook书,非常优秀的一本书,唯一的缺陷是书中的Python版本有点低,还有就是没有协程的相关信息。
在把装饰器定义成类那一章节:
import types
from functools import wraps
class Profiled:
def __init__(self, func):
wraps(func)(self)
self.ncalls = 0
def __call__(self, *args, **kwargs):
self.ncalls += 1
return self.__wrapped__(*args, **kwargs)
def __get__(self, instance, owner):
# print(instance, owner)
if instance is None:
return self
else:
return types.MethodType(self, instance)
书中写了一个用类写的装饰器,其中定义了__get__让我对函数中的__get__实现的逻辑有了更加清晰的认识。
class Spam:
@Profiled
def bar(self, x ):
print(self, x)
当这个方法bar被Profiled类装饰后,返回的是Profiled的实例,单如果在Profiled内部没有定义__get__,一个对象是无法变成spam实例的绑定方法,虽然Profiled实例是一个可调用的对象。
例子中定义了__get__后,当调用这个bar方法,其实就是调用Profiled实例,bar = Profiled(bar),由于bar有__get__方法,首相调用该方法,通过MethodType将Profiled实例的__call__方法传递给instance,也就是spam实例。
这样的话,在运行被装饰的方法的时候,可以同样不需要填写self参数。
from functools import wraps
def decorator1(func):
@wraps(func)
def wrapper(*args):
print('Decorator1')
return func(*args)
return wrapper
class Demo:
# run = decorator1(run)
@decorator1
def run(self, a):
print(f'{a} is run')
d = Demo()
d.run('sidian')
print(d.run)
上面是一个简单的装饰器函数,明显在一个方法被装饰的以后返回的还是一个方法(也可以说一个函数(对于类来说)返回的还是一个函数)
但函数中的__get__方法的作用,使的返回的函数能够重新变成实例的方法。
def __get__(self, instance, owner):
# print(instance, owner)
if instance is None:
return self
else:
return types.MethodType(self, instance)
具体的执行逻辑可能还是跟上面的一样。找不到函数对象里面具体的魔法方法原码,网上是C写的,不懂C
其实这个主要还是面向对象过程的了解,还有就是Python对于函数的介绍的知识好少,函数这个对象内部的结构与逻辑的知识好少。
浙公网安备 33010602011771号