zoukankan      html  css  js  c++  java
  • 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对于函数的介绍的知识好少,函数这个对象内部的结构与逻辑的知识好少。

  • 相关阅读:
    多测师讲解htm_L标题标签001_高级讲师 肖sir
    Shell特殊变量介绍与实践 $0
    shell 变量定义技巧总结
    shell 环境变量的知识小结
    前端 chrome查看html样式基本操作
    shell 命令 env
    date 命令
    shell 命令 set命令
    shell export 命令
    前端 html span标签
  • 原文地址:https://www.cnblogs.com/sidianok/p/12318596.html
Copyright © 2011-2022 走看看