python魔法方法__get__

今天在看到django路由映射类视图时,看到了as_view(),想看看原理,同时提高下对源码得了解

@classonlymethod
def as_view(cls, **initkwargs):
    ...
        
      

发现as_view是被classonlymethod装饰得

class classonlymethod(classmethod):
    def __get__(self, instance, cls=None):
        if instance is not None:
            raise AttributeError("This method is available only on the class, not on instances.")
        return super().__get__(instance, cls)

classonlymethod中只重写了__get__方法,细究之下有几点理解,以防遗忘(大神略过,新手随意),先放一段示例

class A(object):

    def __get__(self, instance, owner):
        print('this is %s' % self)
        return 5


class B(object):
    attr = A()

    def __init__(self):
        self.name = 'test'

    def func1(self):
        print('haha')

    def func2(self):
        pass

先说几个知识 

  1. 描述符:__get__(),__set__(),和__delete__().如果一个对象定义了这些方法中的任何一个,它就是一个描述符.
  2. obj.__dict__显示一个对象得属性
  3. dir(obj)显示对象得所有属性和方法
  4. 一切皆对象,类也是对象

个人心得:

  1.  以前看obj.func() 这句代码是obj+func()这样理解得,现在才反应过来,应该是obj.func+(),也就是以前得理解是对象obj去调用func()方法,现在得理解是取到obj得属性func,然后调用。是不是有好几个疑问,先往下看
  2. B.__dict__结果 :{'__weakref__': , 'func1': , '__doc__': None, 'func2': , 'attr': <__main__.A object at 0x7f2d35c42358>, '__init__': , '__module__': '__main__', '__dict__': }。是不是发现所有的属性和方法都在里面,再来看B得实例b.__dict__.                    b.__dict__结果:{'name': 'test'}  。只有init里面得属性。

  3. 查找一个对象得属性顺序a.x -> a.__dict__['x'] -> type(a).__dict__['x'] -> type(a),先去自己得__dict__找,找不到就去自己得type(对象是由哪个类实例出来得,type就是哪个类)中去找,所以其中一个疑问--为什么b.__dict__中没有func1,func2.却可以取到func1,func2,并进行调用。 不知道大家有没有发现,类B的func1,func2,是function类型,而如果你print(b.fun1)结果是:> ,bound method,一个绑定方法,绑定了什么呢,就是实例本身,绑定到了self,所以实例调用实例方法(b.func1()),类也可以调用实例方法,得自己传self进去,比如(B.func1(B()))

  4. 回到主要问题,如果要获取实例b的attr属性,因为attr指向了A类的实例,直接print(b.attr)会打印一个地址,但是因为A实现了__get__方法,所以当获取属性attr时,会调用attr的__get__方法,并将__get__的return结果作为打印结果(5),如果你得属性是类,不是类得实例,你可以自己搞个元类,把__get__方法加上,type没有

先到这,后续有心得继续补充

参考链接 :https://www.cnblogs.com/flashBoxer/p/9771797.html

你可能感兴趣的:(python魔法方法__get__)