繁体   English   中英

从另一个 python class '继承'@property

[英]'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__来反映对象属性访问的更改。 您希望将默认dirself.modeldir合并。 我通过将它们变成set并使用内置的 set union来做到这一点

def __dir__(self):
    return set(object.__dir__(self)) | set(dir(self.model))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM