我目前正在使用attrs
. 这是一个树状结构,我需要一个父反向链接用于某些目的。OTOH,我想使用冻结的类(有缓存的属性,它们依赖于只读状态)。
这意味着树必须自下而上,在父级之前的子级实例化。为了解决这个问题,我发明了一种特殊的 weakref 对象,它可以被惰性绑定一次。
class LateRef(Generic[T]):
def __init__(self):
self.ref: Optional[T] = None
def set(self, obj: T):
if self.ref is not None:
raise RuntimeError('Reference can only be set once.')
self.ref = weakref.ref(obj)
def __call__(self) -> Optional[T]:
if self.ref is None:
return None
return self.ref()
有自定义初始化代码在子级中创建一个未绑定的引用,并将它们绑定在父级中:
@attr.s(auto_attribs=True, frozen=True)
class Child:
some_attribute:str = "whatever"
def __attrs_post_init__(self):
self.__dict__['parent'] = LateRef()
@attr.s(auto_attribs=True, frozen=True)
class Parent:
children: List[Child] = attr.ib(converter=_deepclone) # off-screen :-)
def __attrs_post_init__(self):
for child in self.children:
child.parent.set(self)
Child.parent
由于child
. _ 以前我把它作为一个自定义工厂的类属性,但后来它变成了一个-属性attrs
,它真的不应该是。例如,我不希望parent
在散列、比较、str 表示等中出现。
代码已经可以工作了,但是:如您所见,我想尽可能地做正确的事情并进行类型注释。直接parent
放入__dict__
意味着通常的工具不知道预期的类型。事实上,他们甚至可能会抱怨该parent
属性根本不存在。
长话短说:有没有办法parent
用类型注释声明为类属性,同时告诉attr.s
跳过/忽略它?还是我忽略了另一种解决方案?
编辑:即如何使静态类型检查器识别parent
属性的类型,而不使其成为attr.ib
.