我有一个带有属性的基类,我想在子类中覆盖它(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)。我发现了一个带有lambda表达式的解决方案:

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

这是使用属性并在子类中覆盖它们的正确解决方案,还是有其他首选方法可以做到这一点?

有帮助吗?

解决方案

我只是喜欢重复 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

其他提示

我不同意所选答案是允许覆盖属性方法的理想方法。如果您希望覆盖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))

这样,可以轻松执行覆盖:

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"

我发现这是在极客在玩

另一种方法,无需创建任何其他类。我添加了一个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)

这是一个非常人为的例子,但你应该明白这一点。

是的,这是做到这一点的方法;属性声明在执行父类定义时执行,这意味着它只能“看到”父类中存在的方法的版本。因此,当您在子类上重新定义一个或多个这些方法时,您需要使用子类的方法版本重新声明该属性。

我同意您的解决方案,这似乎是一种即时模板方法。 本文处理您的问题并提供您的解决方案。

这样的东西会起作用

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)
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top