继承时从超类实例复制属性?

Copying Attributes from Superclass Instance while Inheriting?

我正在尝试创建一个继承自其超类实例的子类,并将其大部分属性基于超类属性。

class Thing:
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c

class ThingWithD(Thing):
    def __init__(self, thing, d):
        self.a = thing.a
        self.b = thing.b
        self.c = thing.c
        self.d = d

ThingWithD.__init__()中声明abc有没有更简洁的方法?

class Thing 定义为:

class Thing:
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c

我可以想到 3 种方法来使用 classical 继承来实现您的要求。首先,是利用您已知的参数并显式索引 args 以提取 a 到 c 和 d,如下所示:

class ThingWithD(Thing):
    def __init__(self, *args):
        self.d = args[-1]
        a_to_c = args[:-1]
        super().__init__(*a_to_c)


thing_with_d = ThingWithD(1,2,3,4)
thing_with_d.a # 1
thing_with_d.d # 4

第二种也是最好的方法是将参数转换为关键字参数,以便更轻松地混合和匹配它们。这是最具可扩展性的解决方案,可以为 ThingWithEThingWithF 铺平道路。

class ThingWithD(Thing):
    def __init__(self, d=None, **kwargs):
        super().__init__(**kwargs)
        self.d = d


thing_with_d = ThingWithD(a=1,b=2,c=3,d=4)
thing_with_d.a # 1
thing_with_d.d # 4

最后一种方法,似乎最接近您已经尝试过的方法,是使用 ThingWithD 作为工厂 class 将 d 添加到 class self referentially。

class ThingWithD(Thing):
    def __init__(self, thing, d):
        super().__init__(thing.a, thing.b, thing.c)
        self.d = d

thing = Thing(1,2,3)
thing_with_d = ThingWithD(thing, 4)
thing_with_d.a # 1
thing_with_d.d # 4

这是一种奇怪的方法,因为这里我们实际上是在创建原始 thing 实例的副本,而且根本不清楚为什么我们要从 Thing 继承。相反,我们可以使用执行以下操作的函数。

def add_d_to_thing(thing, d):
    thing.d = d
    return thing

thing = Thing(1,2,3)
thing_with_d = add_d_to_thing(thing, 4)
thing_with_d.a # 1
thing_with_d.d # 4

这将 return 相同的事物实例,将添加一个 d 属性,并且更易于阅读。

最简洁和面向对象的方法可能是只调用 superclass 的 __init__() 方法并避免重复:

class Thing:
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c

class ThingWithD(Thing):
    def __init__(self, thing, d):
        super().__init__(thing.a, thing.b, thing.c)  # Python 3 only
        self.d = d

thing = Thing(1, 2, 3)
thing_with_d = ThingWithD(thing, 4)
print('{}, {}'.format(thing_with_d.a, thing_with_d.d)) # -> 1, 4

要在 Python 2.x 中做同样的事情,您需要通过明确指定其基础 class 使 Thing 成为新样式 class ] 作为 object 并更改对 superclass 构造函数的调用,如下所示。

如果您进行这两项修改,相同的代码将在 Python 2 和 3 中工作。

class Thing(object):
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c

class ThingWithD(Thing):
    def __init__(self, thing, d):
        super(ThingWithD, self).__init__(thing.a, thing.b, thing.c)
        self.d = d