在python中使用属性时的类属性继承

Class attribute inheritance when using properties in Python

我有以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Desc(object):
    @property
    def color_desc(self):
        return 'Color is ' + self.color

    @property
    def brand_desc(self):
        return 'Brand is ' + self.brand

class Text(Desc):
    def __init__(self):
        self.color = 'blue'
        self.brand = 'volvo'

def main():
    t = Text()
    print t.color_desc

if __name__ == '__main__':
    main()

这在运行时正确工作并输出Color is blue。但是,如果我稍微修改代码,使属性设置为实际的类属性,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Desc(object):
    def __init__(self):
        self._color_desc = color_desc
        self._brand_desc = brand_desc

    @property
    def color_desc(self):
        return self._color_desc

    @color_desc.setter
    def color_desc(self):
        self._color_desc = 'Color is ' + self.color

    @property
    def brand_desc(self):
        return self._brand_desc

    @property
    def brand_desc(self):
        self._brand_desc = 'Brand is ' + self.brand


class Text(Desc):
    def __init__(self):
        self.color = 'blue'
        self.brand = 'volvo'

突然间,它与AttributeError: 'Text' object has no attribute '_color_desc'发生了错误。为什么Text属性首先被正确继承,但在第二个属性中不能访问。对我来说,这两个解决方案似乎做了同样的事情。


您需要调用父类的__init__

这样做:

1
2
3
4
5
class Text(Desc):
    def __init__(self):
        self.color = 'blue'
        self.brand = 'volvo'
        super(Text, self).__init__(0,0)

desc类的init函数定义不正确。这样做:

1
2
3
4
class Desc(object):
    def __init__(self, color_desc, brand_desc):
        self._color_desc = color_desc
        self._brand_desc = brand_desc


在您的Text类中,__init__正在重写Desc.__init__类,因此_color_desc属性没有初始化。


现在还不清楚为什么你认为你的第二个代码片段会起作用。它有以下明显的问题:

  • Desc.__init__使用的两个变量(color_descbrand_desc实际上没有传递给它—您希望它们在全局范围内吗?
  • 你有两个(不同的!)getters,其中一个返回一些东西,没有为brand_desc设置setter。
  • color_descsetter既不接受也不使用任何参数,那么它到底应该设置什么呢?
  • 子类Text.__init__不调用或传递任何内容到超类版本,也不执行任务本身。

我认为你的意图是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Desc(object):

    def __init__(self, color_desc, brand_desc):
        self._color_desc = color_desc
        self._brand_desc = brand_desc

    @property
    def color_desc(self):
        return 'Color is ' + self._color_desc

    @color_desc.setter
    def color_desc(self, new_color):
        self._color_desc = new_color

    @property
    def brand_desc(self):
        return 'Brand is ' + self._brand_desc

    @brand_desc.setter
    def brand_desc(self, new_brand):
        self._brand_desc = new_brand    


class Text(Desc):

    def __init__(self):
        super(Text, self).__init__('blue', 'volvo')

虽然现在看起来Text应该是Desc的一个实例,而不是一个子类。您还可以通过使用只读属性而不向例如color_desc赋值来简化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Desc(object):

    def __init__(self, color, brand):
        self.color = color
        self.brand = brand

    @property
    def color_desc(self):
        return 'Color is ' + self.color

    @property
    def brand_desc(self):
        return 'Brand is ' + self.brand


car = Desc('blue', 'volvo')
car.color = 'red'
print car.color_desc  # Color is red

现在直接设置实例的.color,但.color_desc仍然提供格式良好的版本。