python属性和inheritance
我有一个基类,我想在子类中覆盖(get方法)的属性。 我的第一个想法是这样的:
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)。 我find了一个lambdaexpression式的解决scheme:
age = property(lambda self: self._get_age())
那么这是使用属性并将其覆盖在子类中的正确解决scheme,还是有其他更好的方法来做到这一点?
我只是喜欢重复property()
以及重写类方法时重复@classmethod
装饰器。
虽然这看起来很冗长,至less对于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
另一种方式来做到这一点,而不必创build任何额外的类。 我已经添加了一个设置方法来显示你做什么,如果你只重写其中的一个:
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)
这是一个非常人为的例子,但你应该明白这个主意。
我不同意所选的答案是允许重写财产方法的理想方法。 如果你期望getter和setter被覆盖,那么你可以使用lambda来提供对自己的访问,比如lambda self: self.<property func>
。
这至less适用于Python版本2.4到3.4。
如果有人知道通过使用属性作为装饰器而不是直接调用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"
我在游戏中发现了这个怪胎 。
是的,这是做到这一点的方法。 该属性声明在执行父类定义时执行,这意味着它只能“查看”父类中存在的方法的版本。 所以当你重新定义一个或多个子类的方法时,你需要使用子类的方法版本重新声明属性。
我同意你的解决scheme,这似乎是一个即时模板方法。 本文处理您的问题,并提供您的解决scheme。
像这样的东西将工作
class HackedProperty(object): def __init__(self, f): self.f = f def __get__(self, inst, owner): return getattr(inst, self.f.__name__)() class Foo(object): def _get_age(self): return 11 age = HackedProperty(_get_age) class Bar(Foo): def _get_age(self): return 44 print Bar().age print Foo().age
和@ mr-b一样,但是用装饰器。
class Foo(object): def _get_meow(self): return self._meow + ' from a Foo' def _set_meow(self, value): self._meow = value @property def meow(self): return self._get_meow() @meow.setter def meow(self, value): self._set_meow(value)
这样,可以很容易地执行覆盖:
class Bar(Foo): def _get_meow(self): return super(Bar, self)._get_meow() + ', altered by a Bar'
我遇到了从子类中设置父类的属性的问题。 以下workround扩展父级的属性,但通过直接调用父级的_set_age方法来实现。 皱纹应该始终是正确的。 这是一个javathonic虽然。
import threading class Foo(object): def __init__(self): self._age = 0 def _get_age(self): return self._age def _set_age(self, age): self._age = age age = property(_get_age, _set_age) class ThreadsafeFoo(Foo): def __init__(self): super(ThreadsafeFoo, self).__init__() self.__lock = threading.Lock() self.wrinkled = False def _get_age(self): with self.__lock: return super(ThreadsafeFoo, self).age def _set_age(self, value): with self.__lock: self.wrinkled = True if value > 40 else False super(ThreadsafeFoo, self)._set_age(value) age = property(_get_age, _set_age)