Python 的属性与继承

63 投票
10 回答
54478 浏览
提问于 2025-04-11 18:33

我有一个基类,里面有一个属性,我想在子类中重写这个属性的获取方法。我最开始的想法是这样:

class Foo(object):
    def _get_age(self):
        return 11

    age = property(_get_age)


class Bar(Foo):
    def _get_age(self):
        return 44

但是这样不行(子类 bar.age 返回的是 11)。我找到了一种用 lambda 表达式的解决办法,这个办法有效:

age = property(lambda self: self._get_age())

那么,这种方法是重写属性的正确方式吗?还是说还有其他更好的方法呢?

10 个回答

12

还有一种方法可以做到这一点,不需要创建额外的类。我添加了一个设置方法,来展示如果你只重写其中一个方法该怎么做:

class Foo(object):
    def _get_age(self):
        return 11

    def _set_age(self, age):
        self._age = age

    age = property(_get_age, _set_age)


class Bar(Foo):
    def _get_age(self):
        return 44

    age = property(_get_age, Foo._set_age)

这个例子有点牵强,但你应该能明白我的意思。

21

我不同意这个答案是让属性方法可以被重写的最佳方式。如果你希望获取器和设置器能够被重写,那么可以使用lambda表达式来访问self,像这样:lambda self: self.<property func>

这个方法在Python 2.4到3.6的版本中都能用。

如果有人知道如何使用property作为装饰器,而不是直接调用property(),我很想知道!

举个例子:

class Foo(object):
    def _get_meow(self):
        return self._meow + ' from a Foo'
    def _set_meow(self, value):
        self._meow = value
    meow = property(fget=lambda self: self._get_meow(),
                    fset=lambda self, value: self._set_meow(value))

这样就可以很容易地进行重写:

class Bar(Foo):
    def _get_meow(self):
        return super(Bar, self)._get_meow() + ', altered by a Bar'

所以:

>>> foo = Foo()
>>> bar = Bar()
>>> foo.meow, bar.meow = "meow", "meow"
>>> foo.meow
"meow from a Foo"
>>> bar.meow
"meow from a Foo, altered by a Bar"

我是在geek at play上发现这个的。

72

我个人更喜欢重复使用 property(),就像你在重写类方法时会重复使用 @classmethod 装饰器一样。

虽然这样看起来有点啰嗦,尤其是对于 Python 来说,但你可能会注意到:

1) 对于只读属性,可以把 property 当作装饰器来用:

class Foo(object):
    @property
    def age(self):
        return 11

class Bar(Foo):
    @property
    def age(self):
        return 44

2) 在 Python 2.6 中,属性新增了两个方法 setterdeleter,可以用来给一般属性应用已经为只读属性提供的快捷方式:

class C(object):
    @property
    def x(self):
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

撰写回答