当前位置:  开发笔记 > 编程语言 > 正文

python属性和继承

如何解决《python属性和继承》经验,为你挑选了4个好方法。

我有一个基类,其中包含一个属性(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())

那么这是使用属性并在子类中覆盖它们的正确解决方案,还是有其他首选方法来执行此操作?



1> piro..:

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


等等,所以建议在父类中定义行为的解决方案是重新实现它吗?这不是对DRY的公然违反(不要重复自己)吗?
如果您只想更改getter或setter而不是两者的行为,则此操作将失败。如果仅更改getter,则在尝试使用setter时会出现AttributeError。仅更改设置器几乎是行不通的。定义它的唯一方法(假设未重新定义getter)是使用@ <super class>。<property name> .setter,但这是不正确的,因为它将修改超类而不是子类的属性。绝对不是您想要的。

2> Mr. B..:

我不同意所选答案是允许覆盖属性方法的理想方法.如果您希望覆盖getter和setter,那么您可以使用lambda来提供对self的访问,例如lambda self: self..

这适用于(至少)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"

我在游戏中发现了这个.



3> Kamil Kisiel..:

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

这是一个非常人为的例子,但你应该明白这个想法.



4> James Bennet..:

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

推荐阅读
我我檬檬我我186
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有