我正在编写一个类,它应该是其他类中的子类code.InteractiveInterpreter
。出于某种原因,当您使用多重继承时,该类通常具有的某个方法(compile
)在其子类上不可用。
单继承可以正常工作:
>>> from code import InteractiveInterpreter
>>> class Single(InteractiveInterpreter): pass
...
>>> hasattr(Single(), 'compile')
True
多重继承不会:
>>> class Double(object, InteractiveInterpreter): pass
...
>>> hasattr(Double(), 'compile')
False
虽然翻转了订单但是有效:
>>> class Flipped(InteractiveInterpreter, object): pass
...
>>> hasattr(Flipped(), 'compile')
True
是否有一些我不知道的多重继承的细微细节阻止compile
在某些情况下被继承,或者Python中是否存在导致此问题的错误(给定相关方法的名称)也是内置函数的名称,我觉得这可能是可能的。)
我正在尝试使用InteractiveInterpreter
以外的类重现该问题,但我无法...这样可以正常工作:
>>> class Original():
... def compile(self): pass
...
>>> class Secondary(object, Original): pass
...
>>> hasattr(Secondary(), 'compile')
True
我在Windows 10上使用的是Python 2.7.11,32位。
答案 0 :(得分:1)
您确定Flipped
产生了给定的结果吗?
我通过类似的设置获得以下内容,
>>> from code import InteractiveInterpreter
>>> class Flipped(InteractiveInterpreter, object): pass
...
>>> hasattr(Flipped(), 'compile')
True
基于source of the module,compile
不是类的方法,而是在对象初始化时创建的实例属性。首先从object
继承不会提供属性是有意义的,因为它定义了__init__
并且子类没有调用InteractiveInterpreter.__init__
来分配属性。
答案 1 :(得分:1)
我并不确切知道问题所在,但有一种解决方法是明确调用InteractiveInterpreter
的构造函数,其中实际定义了compile
方法:
class Double(object, InteractiveInterpreter):
def __init__(self, *args, **kwargs):
InteractiveInterpreter.__init__(self, *args, **kwargs)
请注意,简单地调用super(Double, self).__init__(...)
是不够的(至少在我的环境中)。但是,这对我有用
>>> hasattr(Flipped(), 'compile')
True
我的环境: Python 2.7.11(默认,2016年1月5日,12:49:55) [达尔文的GCC 4.2.1兼容的Apple LLVM 7.0.2(clang-700.1.81)]
答案 2 :(得分:0)
当您混合对象和旧样式类时,它似乎是一种东西
Ubuntu 14.04上的Python 2.7.6
我检查了code.InteractiveInterpreter的代码(它使用旧的样式类),然后进行了一些测试: (我只是导入了代码,然后通过代码.__ file__找到了文件)
class Klass:
def __init__(self):
self.compile = 1
class Klass2(object):
def __init__(self):
self.compile = 1
class BlankObj:
pass
class BlankObj2(object):
pass
class Frist(object, Klass):
pass
class Second(BlankObj, Klass):
pass
class Thrid(BlankObj, Klass2):
pass
class Fourth(BlankObj, Klass2):
pass
然后玩弄这些物品:
>>> from testing import Frist, Second, Thrid, Fourth
>>> hasattr(Frist(), 'compile')
False
>>> hasattr(Second(), 'compile')
True
>>> hasattr(Thrid(), 'compile')
True
>>> hasattr(Fourth(), 'compile')
True
>>>
>>> f = Frist()
>>> dir(f)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
>>> s = Second()
>>> dir(s)
['__doc__', '__init__', '__module__', 'compile']
试图制作第五个' class,我从object继承而Klass2导致这个回溯:
>>> class Fifth(object, Klass2):
... pass
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Error when calling the metaclass bases
Cannot create a consistent method resolution
order (MRO) for bases object, Klass2
我不确定为什么会发生这种情况,但它肯定与将对象直接与旧样式类混合有关。