今天在看到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
先说几个知识
- 描述符:__get__(),__set__(),和__delete__().如果一个对象定义了这些方法中的任何一个,它就是一个描述符.
- obj.__dict__显示一个对象得属性
- dir(obj)显示对象得所有属性和方法
- 一切皆对象,类也是对象
个人心得:
- 以前看obj.func() 这句代码是obj+func()这样理解得,现在才反应过来,应该是obj.func+(),也就是以前得理解是对象obj去调用func()方法,现在得理解是取到obj得属性func,然后调用。是不是有好几个疑问,先往下看
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里面得属性。
查找一个对象得属性顺序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()))
回到主要问题,如果要获取实例b的attr属性,因为attr指向了A类的实例,直接print(b.attr)会打印一个地址,但是因为A实现了__get__方法,所以当获取属性attr时,会调用attr的__get__方法,并将__get__的return结果作为打印结果(5),如果你得属性是类,不是类得实例,你可以自己搞个元类,把__get__方法加上,type没有
先到这,后续有心得继续补充