Python: 使用描述符查询缓存发生的方式
Python: Query about the way caching happens using descriptors
我正在尝试使用以下代码使用描述符进行缓存
class TestDesc(object):
def __init__(self,test):
self.test = test
def __get__(self, instance, owner):
if instance is None:
return self
value = instance.__dict__[self.test.__name__] = self.test(instance)
return value
def __set__(self, instance, value):
pass
class MyClass(object):
@TestDesc
def func(self):
time.sleep(5)
return "I am very slow"
c = MyClass()
print(c.func)
print(c.func)
两次打印调用都需要 5 秒,这不是它应有的工作方式。但是如果我删除我添加的 __set__
方法,缓存工作正常。
我无法弄清楚为什么缓存在描述符 class 中的 __set__
方法无法按预期工作。
任何指针表示赞赏。我正在使用 Python 3.4.1
您发现了 数据描述符 和常规描述符之间的区别。数据描述符在实例属性之前处理,而常规描述符在之后处理。
参见参考文档中的Invoking Descriptors:
If the descriptor defines __set__()
and/or __delete__()
, it is a data descriptor; if it defines neither, it is a non-data descriptor.
[...]
Data descriptors with __set__()
and __get__()
defined always override a redefinition in an instance dictionary. In contrast, non-data descriptors can be overridden by instances.
强调我的。
并且来自 Descriptor HowTo Guide:
If an object defines both __get__()
and __set__()
, it is considered a data descriptor. Descriptors that only define __get__()
are called non-data descriptors (they are typically used for methods but other uses are possible).
Data and non-data descriptors differ in how overrides are calculated with respect to entries in an instance’s dictionary. If an instance’s dictionary has an entry with the same name as a data descriptor, the data descriptor takes precedence. If an instance’s dictionary has an entry with the same name as a non-data descriptor, the dictionary entry takes precedence.
您的 TestDecs
描述符有一个 __set__
方法,因此它被认为是一个数据描述符,并且不查询实例属性以允许始终调用 setter。
我正在尝试使用以下代码使用描述符进行缓存
class TestDesc(object):
def __init__(self,test):
self.test = test
def __get__(self, instance, owner):
if instance is None:
return self
value = instance.__dict__[self.test.__name__] = self.test(instance)
return value
def __set__(self, instance, value):
pass
class MyClass(object):
@TestDesc
def func(self):
time.sleep(5)
return "I am very slow"
c = MyClass()
print(c.func)
print(c.func)
两次打印调用都需要 5 秒,这不是它应有的工作方式。但是如果我删除我添加的 __set__
方法,缓存工作正常。
我无法弄清楚为什么缓存在描述符 class 中的 __set__
方法无法按预期工作。
任何指针表示赞赏。我正在使用 Python 3.4.1
您发现了 数据描述符 和常规描述符之间的区别。数据描述符在实例属性之前处理,而常规描述符在之后处理。
参见参考文档中的Invoking Descriptors:
If the descriptor defines
__set__()
and/or__delete__()
, it is a data descriptor; if it defines neither, it is a non-data descriptor.[...]
Data descriptors with
__set__()
and__get__()
defined always override a redefinition in an instance dictionary. In contrast, non-data descriptors can be overridden by instances.
强调我的。
并且来自 Descriptor HowTo Guide:
If an object defines both
__get__()
and__set__()
, it is considered a data descriptor. Descriptors that only define__get__()
are called non-data descriptors (they are typically used for methods but other uses are possible).Data and non-data descriptors differ in how overrides are calculated with respect to entries in an instance’s dictionary. If an instance’s dictionary has an entry with the same name as a data descriptor, the data descriptor takes precedence. If an instance’s dictionary has an entry with the same name as a non-data descriptor, the dictionary entry takes precedence.
您的 TestDecs
描述符有一个 __set__
方法,因此它被认为是一个数据描述符,并且不查询实例属性以允许始终调用 setter。