python对象之属性访问控制--descriptor
在定义class时,会经常使用property、classmethod和staticmethod来定义属性,使属性具有特殊的访问功能。如下所示:
>>>dir(Myclass.__dict__['func'])['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', #说明Myclass的func属性是一个Non-data descriptor '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']>>>Myclass.__dict__['func']<function __main__.func>>>>Myclass.__dict__['func']('dd','hello') #此处可以看到,正常函数对参数的类型没有要求hello>>>Myclass.func<unbound method Myclass.func>>>>Myclass.func(Myclass(), 'hello') # 此处调用的func是descriptor的返回对象,它的第一个参数必须是Myclass的instance,否则会抛TypeErrorhello>>>Myclass().func<bound method Myclass.func of <__main__.Myclass object at 0x22a5410>>>>>Myclass().func('hello') #此处调用的func是descriptor的返回对象,它只需传递一个参数hello
上实验可知:
1 当通过Myclass.__dict__['func']调用时,它是一个正常的函数(同时也是一个non-data descriptor),不是descriptor的执行结果。
2 当通过Myclass.func调用时,它是func.__get__(None, Myclass)的返回对像(unbound method)
3 通过Myclass().func调用时,它是func.__get__(Myclass(),Myclass)的返回对象(bound method)
由此可知,class的一般成员函数,其实一个non-data descriptor,所以通过Myclass().func调用时,实际执行的该函数的__get__(),传参为(Myclass(), Myclass)。从而解释了为什么调用一般的成员函数时,无需传入self参数。