Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中,如何在没有is-a关系的情况下共享属性?_Python_Properties - Fatal编程技术网

在Python中,如何在没有is-a关系的情况下共享属性?

在Python中,如何在没有is-a关系的情况下共享属性?,python,properties,Python,Properties,我有许多Python类型,它们描述了层次结构,因为它们的属性越来越具体。以下是一个例子,而不是试图用文字来描述它: class A: @property def prop1(self): return self._prop1 class B: @property def prop1(self): return self._prop1 @property def prop2(self): retur

我有许多Python类型,它们描述了层次结构,因为它们的属性越来越具体。以下是一个例子,而不是试图用文字来描述它:

class A:
    @property
    def prop1(self):
        return self._prop1

class B:
    @property
    def prop1(self):
        return self._prop1

    @property
    def prop2(self):
        return self._prop2

class C:
    @property
    def prop1(self):
        return self._prop1

    @property
    def prop2(self):
        return self._prop2

    @property
    def prop3(self):
        return self._prop3
因此,当您沿着类列表往下看时,
B
具有
A
的所有属性,然后是一些额外的属性
C
具有
B
的所有属性,然后是一些额外的属性,依此类推。我希望尽可能减少上述定义的重复


一个明显的解决方案是使用继承,使
B
成为
a
的子类,等等。然而,这些类型的语义并不遵循is-a关系;我不希望
isinstance(boobject,A)
True
。Python中是否有其他方法可以直接允许这种共享属性而不使用子类?

您可以使用装饰器:

def has_prop1(cls):
    @property
    def prop1(self):
        return self._prop1

    cls.prop1 = prop1

    return cls

@has_prop1
class A(object):
    pass
合成过程如下所示:

@has_prop1
@has_prop2
class B(object):
    pass
def has_many_properties(cls):
    return has_prop1(has_prop2(has_prop3(cls)))

@has_many_properties
class C(object):
    pass
甚至像这样:

@has_prop1
@has_prop2
class B(object):
    pass
def has_many_properties(cls):
    return has_prop1(has_prop2(has_prop3(cls)))

@has_many_properties
class C(object):
    pass
你说“我不想撒谎说C是A,但实际上不是。类型的特征不符合子类化的语义。”对于你模糊的例子,不清楚该怎么做

如果您这样说是因为
类A
中有不适用于
类C
的附加功能,那么我将从组合中取出类的属性部分,因此您有
A
B
C
包含
AProps
BProps
,和
CProps
,并为属性类提供适当的继承关系


如果没有这样的附加功能,而且属性是按照您所展示的方式构建的,这不仅仅是巧合,那么请在心里将
class A
重命名为
class ProvidesProp1
,注意
class C
是一个提供
prop1
的类,并接受
C类
因此为-a
a类

您可以使用组合而不是子类化。我想您的意思是,我可以在每个
B
中包含
A
,然后重新实现
B
的属性访问器以从
A
实例中提取。这是我想到的另一个解决方案,但它似乎并不比上面所示的实现更紧凑。为什么您真正关心
isinstance
返回什么?你真的有很好的理由打电话给isinstance吗?可能没有,但万一有人打电话给你,我不想撒谎说
C
a
,其实它不是。类型的特征不符合子类化的语义。