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对于函数的介绍的知识好少,函数这个对象内部的结构与逻辑的知识好少。

猜你喜欢

转载自www.cnblogs.com/sidianok/p/12318596.html