共计 2905 个字符,预计需要花费 8 分钟才能阅读完成。
属性搜索优先级和 descriptor
######################## | |
# 定义 | |
######################## | |
# 数据描述符 | |
class DataDesc(object): | |
def __init__(self, *args, **kwargs): | |
pass | |
def __get__(self, instance, cls): | |
print(instance is None) | |
return 'DataDesc' | |
def __set__(self, instance, value): | |
return None | |
def __delete__(self, instance): | |
return None | |
# 数据描述符 | |
class DataDesc2(object): | |
def __init__(self, *args, **kwargs): | |
pass | |
def __get__(self, instance, cls): | |
return 'DataDesc2' | |
def __set__(self, instance, value): | |
return None | |
# 非数据描述符 | |
class NonDataDesc(object): | |
def __init__(self, *args, **kwargs): | |
pass | |
def __get__(self, instance, cls): | |
print(instance is None) | |
return 'NonDataDesc' | |
class Foo(object): | |
test_attr = DataDesc() | |
test_attr2 = DataDesc() | |
test_attr3 = NonDataDesc() | |
test_attr4 = 'test_attr4' | |
def __getattr__(self, item): | |
return 'hehe__getattr__' | |
######################## | |
# 一般情况 | |
######################## | |
foo = Foo() | |
'''1. foo.__dict__['test_attr4'] | |
2. for cls in Foo.__mro__: | |
cls.__dict__['test_attr4'] | |
3. foo.__getattr__('test_attr4') | |
''' | |
print(foo.test_attr4) | |
foo.__dict__['test_attr4'] = 666 | |
print(foo.test_attr4) | |
print(id(foo.test_attr4) == id(foo.__dict__['test_attr4'])) | |
foo.__dict__.pop('test_attr4') | |
print(foo.test_attr4) | |
print(foo.test_attr5) | |
print(foo.__getattr__('test_attr5')) | |
######################## | |
# 数据型描述符 | |
######################## | |
foo = Foo() | |
'''1. type(foo).__dict__['test_attr'].__get__(foo, type(foo)) | |
2. foo.__dict__['test_attr4'] | |
3. for cls in Foo.__mro__: | |
cls.__dict__['test_attr4'] | |
4. foo.__getattr__('test_attr4') | |
''' | |
print(foo.test_attr) | |
foo.__dict__['test_attr'] = 666 | |
print(foo.test_attr) | |
print(id(foo.test_attr) == id(foo.__dict__['test_attr'])) | |
delattr(Foo, 'test_attr') | |
print(foo.test_attr) | |
print(id(foo.test_attr) == id(foo.__dict__['test_attr'])) | |
######################## | |
# 非数据型描述符 | |
######################## | |
foo = Foo() | |
'''1. foo.__dict__['test_attr4'] | |
2. type(foo).__dict__['test_attr'].__get__(foo, type(foo)) | |
3. for cls in Foo.__mro__: | |
cls.__dict__['test_attr4'] | |
4. foo.__getattr__('test_attr4') | |
''' | |
print(foo.test_attr3) | |
foo.__dict__['test_attr3'] = 666 | |
print(foo.test_attr3) | |
print(id(foo.test_attr3) == id(foo.__dict__['test_attr3'])) | |
del foo.test_attr3 | |
print(foo.test_attr3) | |
######################## | |
# 类调用描述符 | |
######################## | |
'''FOO.__dict__['test_attr'].__get__(None, FOO)''' | |
print(Foo.test_attr2) | |
print(Foo.test_attr3) | |
######################## | |
# __getattribute__ | |
######################## | |
''' | |
如果被重写, 上面代码介绍的东西会被覆盖掉 | |
除非函数内部调用 object.__getattribute__ | |
否则别这么干 | |
''' | |
class Foo2(object): | |
test_attr = DataDesc() | |
test_attr2 = DataDesc() | |
test_attr3 = NonDataDesc() | |
test_attr4 = 'test_attr4' | |
def __getattribute__(self, item): | |
return 'in __getattribute__' | |
foo = Foo2() | |
print(foo.test_attr3) | |
######################## | |
# 例子 | |
######################## | |
import time | |
class LazyProperty(object): | |
def __init__(self, func): | |
self.func = func | |
def __get__(self, instance, cls): | |
if instance is not None: | |
val = self.func(instance) | |
setattr(instance, self.func.__name__, val) | |
return val | |
class Foo3(object): | |
@LazyProperty | |
def method(self): | |
time.sleep(5) | |
return 666 | |
foo3 = Foo3() | |
time1 = time.time() | |
print(foo3.method) | |
time2 = time.time() | |
print(time2 - time1) | |
print(foo3.method) | |
print(time.time() - time2) |
正文完