Pet*_*ann 57 python polymorphism inheritance properties
我有一个基类,其中包含一个属性(get方法),我想在子类中覆盖它.我的第一个想法是:
class Foo(object):
def _get_age(self):
return 11
age = property(_get_age)
class Bar(Foo):
def _get_age(self):
return 44
Run Code Online (Sandbox Code Playgroud)
这不起作用(子类bar.age返回11).我发现了一个带有lambda表达式的解决方案:
age = property(lambda self: self._get_age())
Run Code Online (Sandbox Code Playgroud)
那么这是使用属性并在子类中覆盖它们的正确解决方案,还是有其他首选方法来执行此操作?
pir*_*iro 65
我只是喜欢重复这个property(),以及@classmethod在重写类方法时重复装饰器.
虽然这看起来非常冗长,但至少对于Python标准,您可能会注意到:
1)对于只读属性,property可以用作装饰器:
class Foo(object):
@property
def age(self):
return 11
class Bar(Foo):
@property
def age(self):
return 44
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
Mr.*_*. B 16
我不同意所选答案是允许覆盖属性方法的理想方法.如果您希望覆盖getter和setter,那么您可以使用lambda来提供对self的访问,例如lambda self: self.<property func>.
这适用于(至少)Python版本2.4到3.6.
如果有人知道通过使用属性作为装饰器而不是直接的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))
Run Code Online (Sandbox Code Playgroud)
这样,可以轻松执行覆盖:
class Bar(Foo):
def _get_meow(self):
return super(Bar, self)._get_meow() + ', altered by a Bar'
Run Code Online (Sandbox Code Playgroud)
以便:
>>> 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"
Run Code Online (Sandbox Code Playgroud)
我在游戏中发现了这个.
Kam*_*iel 11
另一种方法,无需创建任何其他类.我添加了一个set方法来显示你只做了两个中的一个:
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)
Run Code Online (Sandbox Code Playgroud)
这是一个非常人为的例子,但你应该明白这个想法.
是的,这是做到这一点的方法; 属性声明在执行父类定义时执行,这意味着它只能"看到"父类中存在的方法的版本.因此,当您在子类上重新定义一个或多个这些方法时,您需要使用子类的方法版本重新声明该属性.
可能的解决方法可能如下所示:
class Foo:
def __init__(self, age):
self.age = age
@property
def age(self):
print('Foo: getting age')
return self._age
@age.setter
def age(self, value):
print('Foo: setting age')
self._age = value
class Bar(Foo):
def __init__(self, age):
self.age = age
@property
def age(self):
return super().age
@age.setter
def age(self, value):
super(Bar, Bar).age.__set__(self, value)
if __name__ == '__main__':
f = Foo(11)
print(f.age)
b = Bar(44)
print(b.age)
Run Code Online (Sandbox Code Playgroud)
它打印
Foo: setting age
Foo: getting age
11
Foo: setting age
Foo: getting age
44
Run Code Online (Sandbox Code Playgroud)
这个想法来自 David Beazley 和 Brian K. Jones 所著的《Python Cookbook》。在 Debian GNU/Linux 9.11 上使用 Python 3.5.3(延伸)