从Python的超类中获取属性

9

我有一个基类,一堆子类,对于这些子类的每一个,我都有另一组子子类。例如:

class BaseClass(object):
    def __init__(self):
        with open(config.txt) as f
            self.config_array = f.readlines()

class FirstOrderSubClass(BaseClass):
    def __init__(self, name):
        self.name = name

class SecondOrderSubClass(FirstOrderSubClass):
    def __init__(self, name, version):
        self.name = name
        self.version = version
        super(SecondOrderSubClass, self).__init__(self.name)
        # needed to access self.config_array
        print self.config_array

我需要获取SecondOrderSubClass__init__()方法,以完成以下赋值:self.lines = self.config_array
编辑:添加行print self.config_array。如果我运行代码,将会得到以下结果:
TypeError: __getattr__() takes exactly 1 argument (2 given)

你已经继承了该属性,在 FirstOrderSubClass 中添加 super(FirstOrderSubClass, self).__init__() - Padraic Cunningham
2个回答

9

在运行BaseClass.__init__()以设置属性之前,您无法访问self.config_array

要么修复FirstOrderSubClass以调用基类__init__,要么直接调用它。

修复FirstOrderSubClass可能是最好的方法:

class FirstOrderSubClass(BaseClass):
    def __init__(self, name):
        super(FirstOrderSubClass, self).__init__()
        self.name = name

然而,您的__init__方法签名不匹配,因此您不能依赖于协作行为;一旦在层次结构中添加了混合类,事情就可能会出现问题并且很可能会出现问题。请参见 Raymond Hettinger 的 *Python's super() is considered super! 或其后续 PyCon presentation,以解释为什么要使签名匹配。

直接调用未绑定的BaseClass.__init__方法(显式传入self)也可以起到作用:

class SecondOrderSubClass(FirstOrderSubClass):
    def __init__(self, name, version):
        super(SecondOrderSubClass, self).__init__(name)
        self.version = version
        BaseClass.__init__(self)

请注意,如果您要求FirstOrderSubClass.__init__执行完全相同的操作,则在那里分配self.name没有意义。
使用super()的正确方法是使所有方法至少接受所有相同的参数。由于object.__init__()从不这样做,因此这意味着您需要一个不使用super()的标志类; BaseClass在这里非常适合。您可以使用*args**kw来捕获任何其他参数,并仅忽略这些参数以使协作子类化起作用:
class BaseClass(object):
    def __init__(self, *args, **kw):
        with open(config.txt) as f
            self.config_array = f.readlines()

class FirstOrderSubClass(BaseClass):
    def __init__(self, name, *args, **kw):
        super(FirstOrderSubClass, self).__init__(*args, **kw)
        self.name = name

class SecondOrderSubClass(FirstOrderSubClass):
    def __init__(self, name, version, *args, **kw):
        super(SecondOrderSubClass, self).__init__(name, *args, **kw)
        self.version = version

1
谢谢您的解释!这正是我所缺少的。如果BaseClass.__init__没有运行,当然我就无法访问其中的任何内容!非常感谢您指向这个讲座,我学习Python已经有几个月了,我正在尝试阅读/观看我能找到的任何东西。 - rafforaffo

1

你必须调用FirstOrderSubClasssuper方法:

class BaseClass(object):
    def __init__(self):
        with open("config.example.txt",'w') as f:
            f.write("Hello world")
        with open("config.example.txt") as f:
            self.config_array = f.readlines()

class FirstOrderSubClass(BaseClass):
    def __init__(self, name):
        super(FirstOrderSubClass,self).__init__()
        self.name = name

class SecondOrderSubClass(FirstOrderSubClass):
    def __init__(self, name, version):
        self.name = name
        self.version = version
        super(SecondOrderSubClass, self).__init__(self.name)
        # needed to access self.config_array

grandchild = SecondOrderSubClass("peter",2.0)
print grandchild.config_array
##>>> 
##['Hello world']

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接