【问题标题】:How to use super() to update a value in a specific instance of the parent?如何使用 super() 更新父级特定实例中的值?
【发布时间】:2018-09-18 21:56:22
【问题描述】:

我想使用 super 函数将字符串写入父对象的特定实例的列表中。到目前为止,这是我的代码:

#!/usr/bin/env python
# test.py

class Master(object):
    def __init__(self):
        pass

class Sub1(Master):
    list = []
    def __init__(self):
        pass

class Sub2(Sub1):
    def __init__(self, name):
        super(Sub2, self).list.append(name)

m = Master()
m.foo = Sub1()
m.foo.bar = Sub2('something')

m.bla = Sub1()
m.bla.blub = Sub2('else')

print(m.foo.list)

在这种情况下,输出当然是

['something', 'else']

但我希望它只是 'something'

我怎样才能做到这一点?

我试过了:

class Sub1(Master):
    def __init__(self):
        self.list = []

产量:

AttributeError: 'super' object has no attribute 'list'

有简单的解决方案吗?

【问题讨论】:

  • 我认为您不应该在这里使用继承。也许将parent 参数传递给__init__
  • 你必须从你的Sub2__init__方法调用Sub1构造函数。
  • 你确定你真的需要继承吗?继承是is-a 关系,而不是“包含”关系。
  • 不,我不确定我是否需要继承.... 在这种情况下,它看起来像 Master 包含 Sub1 其中包含 Sub2,但后来我真的想继承某些参数和方法。在现实生活中,它类似于动物 --> 哺乳动物 --> 狗。

标签: python inheritance


【解决方案1】:

您的实际问题似乎出在您初始化list 的方式上。

您需要在__init__() 中分配它,而不是在类主体中,以避免它在类的所有实例之间共享(请参阅Static class variables in Python)。

class Sub1(Master):
    def __init__(self):
        self.list = []

【讨论】:

  • OP 说他们试过了,但出错了。在这一点上,你真的不能称之为答案。
【解决方案2】:

正如您所指出的,如果您将lst 定义为Sub1 中的类属性,它会在所有实例之间共享,这不是您想要的。因此,您必须将lst 定义为Sub1 中的实例属性,但它必须由Sub1 的实例而不是Sub2 的实例管理。这是一个修改后的代码,可以提供您所期望的:

class Master(object):
    def __init__(self):
        super().__init__()

class Sub1(Master):
    def __init__(self):
        super().__init__()
        self.lst = []
    def add(self, item):
        self.lst.append(item.name)

class Sub2(Sub1):
    def __init__(self, name):
        super().__init__()
        self.name = name

m = Master()
m.foo = Sub1()
m.foo.add(Sub2('something'))

m.bla = Sub1()
m.bla.add(Sub2('else'))

print(m.foo.lst)
print(m.bla.lst)

这是输出:

['something'] <-- m.foo.lst
['else'] <-- m.bla.lst

Rem1:当使用super() 时,整个类层次结构必须是协作的(即在构造函数中使用super())。

Rem2:在Python3中,super()等价于super(classname, self)

Rem3:不要使用list作为变量名(它是内置类型)

Rem4:我的代码仅在列表中存储name 属性以模仿您给出的示例,但我想在现实生活中您宁愿在该列表中存储Sub2 的实例。为此,只需删除add函数中的.name


编辑:对我的回答进行更多思考后,我想到了另一个可能更接近您最初尝试的解决方案。让我知道哪一个最适合您的实际问题...

class Master(object):
    def __init__(self):
        super().__init__()

class Sub1(Master):
    def __init__(self):
        super().__init__()
        self.lst = []

class Sub2(Sub1):
    def __init__(self, parent, name):
        super().__init__()
        parent.lst.append(name)

m = Master()
m.foo = Sub1()
m.foo.bar = Sub2(m.foo, 'something')

m.bla = Sub1()
m.bla.blub = Sub2(m.bla, 'else')

print(m.foo.lst)
print(m.bla.lst)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多