python魔法方法__get__

本文通过探讨Django的as_view()和classonlymethod装饰器,详细解析了Python中的__get__方法。介绍了描述符协议以及对象属性查找顺序,展示了如何通过__get__方法实现属性访问的自定义行为,尤其是当属性为类实例时如何调用其方法。通过示例和解释,帮助读者更好地理解Python中的方法绑定和属性访问机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天在看到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__': <attribute '__weakref__' of 'B' objects>, 'func1': <function B.func1 at 0x7f2d35c2ab70>, '__doc__': None, 'func2': <function B.func2 at 0x7f2d35c2abf8>, 'attr': <__main__.A object at 0x7f2d35c42358>, '__init__': <function B.__init__ at 0x7f2d35c2aa60>, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'B' objects>}。是不是发现所有的属性和方法都在里面,再来看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 B.func1 of <__main__.B object at 0x7f5eabd7f278>> ,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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值