Python 的属性与继承
我有一个基类,里面有一个属性,我想在子类中重写这个属性的获取方法。我最开始的想法是这样:
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 中,属性新增了两个方法 setter
和 deleter
,可以用来给一般属性应用已经为只读属性提供的快捷方式:
class C(object):
@property
def x(self):
return self._x
@x.setter
def x(self, value):
self._x = value