[英]'Inherit' @property from another python class
假设我有两个类无法通过 inheritance 链接,但可以链接其中的实例:
class model:
def __init__(self):
self._alpha = [0,1,2,3]
@property
def alpha(self):
return self._alpha
@alpha.setter
def alpha(self, inList):
self._alpha = inList
class solver:
def __init__(self, inModel):
self.model = inModel
有没有办法让我将solver.alpha
定义为model.alpha
而不必写出更多样板文件:
class solver:
def __init__(self, inModel):
self.model = inModel
@property
def alpha(self):
return self.model.alpha
@alpha.setter
def alpha(self, inList):
self.modle.alpha = inList
您可以编写描述符 class 来自动化该过程:
class PathDescriptor:
def __init__(self, *paths):
self.paths = paths
def __get__(self, obj, objtype=None):
for path in self.paths:
obj = getattr(obj, path)
return obj
def __set__(self, obj, value):
for path in self.paths[:-1]:
obj = getattr(obj, path)
setattr(obj, self.paths[-1], value)
例子:
class solver:
def __init__(self, inModel):
self.model = inModel
alpha = PathDescriptor('model', 'alpha')
m = model()
s = solver(m)
print(s.alpha) # [0, 1, 2, 3]
另一个解决方案是通过覆盖__getattr__
将属性访问从solver
“重定向”到model
:
class solver:
def __init__(self, inModel):
self.model = inModel
def __getattr__(self, name):
# note that this only gets called if the normal attribute access failed
# so normal instance variables will still work.
return getattr(self.model, name)
用法:
m = model()
s = solver(m)
print(s.alpha) # [0, 1, 2, 3]
这仅在获取属性时有效,为了将其扩展为包括设置(以及删除),您需要覆盖__setattr__
(和__delattr__
)但那些没有仅在正常属性访问失败时才被调用的好特性,所以你需要检查:
def __setattr__(self, name, value):
try:
object.__setattr__(self, name, value) # try normal attribute access
except AttributeError:
setattr(self.model, name, value)
有了这个 solotion,您不需要列出model
您想要在solver
上的每个属性,但您也无法控制它。 另一个限制是这仅适用于一个 object,例如,您不能有两个模型,其中一些属性来自一个 model,而一些属性来自另一个 model。
编辑:
您可能希望通过覆盖__dir__
来反映对象属性访问的更改。 您希望将默认dir
与self.model
的dir
合并。 我通过将它们变成set
并使用内置的 set union来做到这一点
def __dir__(self):
return set(object.__dir__(self)) | set(dir(self.model))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.