【发布时间】:2017-03-08 20:21:20
【问题描述】:
我有一个用于从数据存储延迟加载的描述符,如果数据存储不可用,它会返回默认值。描述符工作正常,除了我希望默认值是提供的类类型的实例,该类类型与定义描述符的类类型相同(树层次结构需要)。理想情况下我想这样做
from weakref import WeakKeyDictionary
class Descriptor(object):
def __init__(self, classType=None):
self.classType = classType
self.values = WeakKeyDictionary()
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner):
print("name:", self.name)
if instance not in self.values:
self.values[instance] = self.classType()
return self.values[instance]
def __set__(self, instance, value):
self.values[instance] = value
class Item1(object):
pass
class Item2(object):
parent1 = Descriptor(Item1)
parent2 = Descriptor(Item2)
item2 = Item2()
print(item2.parent1)
print(item2.parent2)
但显然 parent2 的描述符不能传递给它正在定义的类。因此,另一种方法是在定义类之后分配 parent2:
class Item2(object):
parent1 = Descriptor(Item1)
Item2.parent2 = Descriptor(Item2)
但是,在这种情况下,创建构造函数时似乎没有调用 __set_name__ 方法,因为给出了以下错误:
name: parent1
<__main__.Item1 object at 0x021F4890>
Traceback (most recent call last):
File "..\setNameTest.py", line 28, in <module>
print(item2.parent2)
File "..\setNameTest.py", line 10, in __get__
print("name:", self.name)
AttributeError: 'Descriptor' object has no attribute 'name'
似乎可行的是在类中创建描述符后将 itemClass 值分配给 parent2,但在整个代码库中使用似乎很笨重:
class Item2(object):
parent1 = Descriptor(Item1)
parent2 = Descriptor()
Item2.__dict__['parent2'].classType = Item2
有没有更清洁的方法?
2017 年 3 月 9 日编辑: 根据https://stackoverflow.com/a/6995286/1834561,如果实例为 None,则可以通过从 Descriptor.__get__ 返回 self 来稍微清理一下此方法,即
def __get__(self, instance, owner):
if instance is None:
return self
print("name:", self.name)
if instance not in self.values:
self.values[instance] = self.classType()
return self.values[instance]
现在可以在类定义之外分配classType
Item2.parent2.classType = Item2
【问题讨论】:
-
您可以使用元类,但我不确定您的描述符能否正常工作...您想用
__set_name__方法做什么? -
我正在使用 _set_name_ 获取描述符分配的名称,并在与数据存储交互时使用该名称
-
抱歉,这是 Python 36 的新功能
标签: python