【问题标题】:Fields in all subclasses of a class一个类的所有子类中的字段
【发布时间】:2016-06-19 13:54:17
【问题描述】:

假设我们有一个类A,一个继承自A 的类B,以及一个继承自B 的类CDE

我们希望所有这些类都有一个用默认值初始化的属性_f,并且我们希望该属性是可变的,并且对类的每个实例都有一个单独的值,即它不应该是静态的, 常量值A 被所有子类使用。

一种方法是在A的__init__方法中定义_f,然后在子类中依赖这个方法:

class A:
    def __init__(self):
        self._f = 'default_value'

class B(A):
    def __init__(self):
        super(B, self).__init__()

class C(B):
    def __init__(self):
        super(C, self).__init__()

有什么好的 Pythonic 方法可以避免这种情况,并且可能避免使用元类?

【问题讨论】:

  • 请注意,如果所有子类实现都调用超类实现,则可以将它们排除在外。 class B(A): pass 可以正常工作。您是在寻找 class 属性还是常规 instance 属性?你能举一个不那么抽象的例子吗?
  • 取决于字段 _f 是指可变类型还是不可变类型。
  • _f 应该是类字段还是实例字段?
  • 应该是实例字段,并且应该是可变的
  • @jonrsharpe 我对此感到非常惊讶,因为我已经阅读了这篇文章:link,并认为我什至不应该尝试它(未来的教训)。谢谢。

标签: python inheritance


【解决方案1】:

如果您的目标是通过消除调用基类构造函数的需要来简化子类构造函数,但仍然能够覆盖子类中的默认值,那么有一个常见的范例就是利用 Python 将返回类的值如果实例上不存在属性。

使用一个稍微具体的例子,而不是做...

class Human(object):

    def __init__(self):
        self._fingers = 10

    def __repr__(self):
        return 'I am a %s with %d fingers' % (self.__class__.__name__, self._fingers)


class MutatedHuman(Human):

    def __init__(self, fingers):
        super(MutatedHuman, self).__init__()
        self._fingers = fingers


print MutatedHuman(fingers=11)
print Human()

...你可以使用...

class Human(object):

    _fingers = 10

    def __repr__(self):
        return 'I am a %s with %d fingers' % (self.__class__.__name__, self._fingers)


class MutatedHuman(Human):

    def __init__(self, fingers):
        self._fingers = fingers


print MutatedHuman(fingers=11)
print Human()

...两者都输出...

I am a MutatedHuman with 11 fingers
I am a Human with 10 fingers

重要的一点是第二个示例中的行self._fingers = fingers 不会覆盖类Human 上设置的默认值,而只是在引用为self._fingers 时隐藏它。

当变量引用可变类型(例如列表)时,这有点麻烦。您必须小心,不要对默认值执行操作会修改它,尽管执行self.name = value 仍然是安全的。

与其他方法相比,这种方法的简洁之处在于它往往会导致代码行数更少,这通常是一件好事 (tm)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-29
    • 1970-01-01
    • 2012-03-13
    • 2019-03-01
    • 2013-06-05
    相关资源
    最近更新 更多