我正在尝试将ConfigParser子类化。在尝试访问_sections
时,它说
'acc' object has no attribute '_sections'
示例代码(python 2.7):
import ConfigParser
class acc(object, ConfigParser.RawConfigParser):
def __init__(self, acc_file):
super(acc,self).__init__()
self.lol = 1
print self.has_section(self.lol)
a=acc(1)
答案 0 :(得分:3)
问题描述得更好here。
这是Python的Method Resolution Order。
所以,实际发生的事情是MRO“链接”在绑定旧样式类时表现不佳。或者具体 - 不称为超级
的类在您的代码中,configParser.RawConfigParser__init__(..)
从不调用。要解决此问题,您可以手动调用它(只需在ConfigParser.RawConfigParser.__init__(self ...)
的{{1}}中添加acc
),但我不确定这是推荐的,甚至是有效的。
您的另一个选择是使所有类符合新样式,并调用init
或旧样式,并显式初始化。
唯一可行的方法是,如果所有经典风格的类在<{1}}的输出中>>之后 ,特别是super
之后的所有新风格类。这会阻止Class.mro()
调用它们。
由于这种情况,other answer不是很安全:
object
修复其他答案:将这些行添加到super
的{{1}}应该通知显式实例化类:
class TheClassicClass:
def __init__(self):
print "instantiating clasic class!"
self._msg = "the classic class!"
def m(self):
print self._msg
class acc(ConfigParser.RawConfigParser, TheClassicClass, object):
def __init__(self, acc_file):
super(acc,self).__init__()
self.lol = 1
print self.has_section(self.lol)
a=acc(1)
a.m()
要确认代码中的问题,让我们尝试在简单的设置中重现此问题...
我们将制作旧的(经典)课程:
acc
调用__init__
的新样式类:
ConfigParser.RawConfigParser.__init__(self)
TheClassicClass.__init__(self)
在最简单的情况下,我们手动调用class AClassic:
def __init__(self):
print "init aclassic"
class BClassic:
def __init__(self):
print "init bclassic"
self.name = "bclassic"
def m(self):
print "print from " + self.name
以确保实例化类。这看起来像是:
super
在这种情况下,depth-first, left-to-right是MRO的顺序。
输出:
旧式
init aclassic
init bclassic
从bclassic打印
现在让我们尝试使用class ANew(object):
def __init__(self):
print "init anew"
super(ANew, self).__init__()
class BNew(object):
def __init__(self):
print "init bnew"
super(BNew, self).__init__()
def m(self):
print "print from bnew"
看起来像这样的新样式:
__init__
由于两个类都调用class TestOldStyle(AClassic, BClassic):
def __init__(self):
AClassic.__init__(self)
BClassic.__init__(self)
self.m()
print "old style"
TestOldStyle()
,因此它们都被实例化,输出为:
重新启动
init bnew
现在,我们尝试使用经典风格类的一些“混合”(ConfigParser.RawConfigParser is a classic-style-class,而不能调用super
:
# will init ANew and BNew
class TestNewSuper(ANew, BNew, object):
def __init__(self):
super(TestNewSuper, self).__init__()
TestNewSuper()
输出:
重新启动
立即例外:
super
这是因为super
未实例化。
更多意外行为的例子:
# will init ANew , but not BClassic
class TestOldStyleSuper(ANew, BClassic):
def __init__(self):
super(TestOldStyleSuper, self).__init__()
self.m()
将初始化Traceback (most recent call last):
File "./inhert.py", line 35, in <module>
TestOldStyleSuper()
File "./inhert.py", line 33, in __init__
self.m()
File "./inhert.py", line 15, in m
print "print from " + self.name
AttributeError: 'TestOldStyleSuper' object has no attribute 'name'
和BClassic
,但不会# init ANew, BClassic
class TestHybrid(ANew, BClassic, BNew):
def __init__(self):
super(TestHybrid, self).__init__()
self.m()
TestHybrid()
:
重新启动
init bclassic
从bclassic打印
创建一个不存在的MRO:
ANew
例外:
BClassic
答案 1 :(得分:2)
按如下方式颠倒子类的顺序:
import ConfigParser
class acc(ConfigParser.RawConfigParser, object):
def __init__(self, acc_file):
super(acc, self).__init__()
self.lol = 1
print self.has_section(self.lol)
a=acc(1)