当您从模块而不是 Python 中的 class 继承时会发生什么?

What happens when you inherent from a module instead of a class in Python?

我最近遇到了 this question

import Object

class Visitor(Object):

    def __init__(self):
        super(Visitor,self).__init__()
    def visit(self, obj):
        pass
    def getIsDone(self):
        return False
    isDone = property(fget =lambda self:self.getIsDone())

I get this error:

TypeError: module.__init__() takes at most 2 arguments (3 given)

及其答案:

class A:pass
print(A)              #outputs <class '__main__.A'>
import urllib
print(urllib)         #outputs <module 'urllib' from '/usr/lib/python3.2/urllib/__init__.py'>

Your error is happening because Object is a module, not a class. So your inheritance is screwy.

Change your import statement to:

from Object import ClassName

and your class definition to:

class Visitor(ClassName):

or

change your class definition to:

class Visitor(Object.ClassName):
   etc

我对这个答案不是很满意,因为我不太确定我是如何从该错误消息中得出我不小心从模块而不是 class 继承的结论的。我想知道是否有人可以详细说明为什么会发生此错误以及给出的参数到底是什么?当 python 解释器遇到这样的代码时: class Employee(Person) 发生了什么事?回答者所说的我的继承是古怪的到底是什么意思?感谢您对资源的任何解释或引用。

要找出你哪里出错了,在这种情况下你真的不需要看错误信息,从代码本身就很清楚了。

import foo

总是意味着 foo 是一个模块(与 from foo import bar 相反,其中 bar 可以是一个模块,class,函数是一个变量等等)。这是命名约定帮助我们的地方,如果遵循 PEP8,那么可以很容易地区分 classes 和模块。你问题中的代码不遵循这显然不利于其他人理解。

一旦你知道你已经尝试 subclass/inherit 一个 module 剩下的就不是那么棘手了。

大多数模块没有定义 __init__ 这意味着当你试图访问它时,它只是试图在继承链中找到它(如果你真的对此感兴趣,你可以阅读 python 继承、mro 等,但我怀疑这不是让你在这里感到困惑的原因。)并找到内置的 class module 其中(执行 import Object;type(Object)import os; type(os)) 有一个 __init__ 期望与您重写的方法不同的参数。如果您的方法具有与上面完全相同数量的参数,那么调试起来会更加棘手。

该错误消息似乎对您没有帮助,因为 python 无法理解您是有意覆盖 module.__init__ 还是某些 class 的 __init__。尝试

import os
help(type(os))

如果你把一个叫做BaseClass的对象放在继承列表中,那么解释器会在内部调用它:

type(BaseClass).__init__(cls, name_of_subclass, (BaseClass,), dict_of_subclass)
# or simpler
type(BaseClass)(name_of_subclass, (BaseClass,), dict_of_subclass)

您可以创建一个虚拟 BaseClass 来测试它

class Meta(object):
   def __init__(self, name,   base,  subcls):
      print (self, name,   base,  subcls)

Base = Meta('','','')

class Test(Base):
    prop1="hello"

输出:

<__main__.Meta object at 0x7f7471666bd0>
<__main__.Meta object at 0x7f7471666c50> Test (<__main__.Meta object at 0x7f7471666bd0>,) {'__module__': '__main__', 'prop1': 'hello'}

回答你的问题:当解释器看到class Employee(Person): pass时,会发生以下情况:

type(Person).__init__(cls, 'Employee', (Person,), {'__module__': '__main__'})

如果 Person 是正常的 class,type(person) 将 return type 本身。然后 type.__init__ 会被调用。

如果 Person 是一个模块,type(person) 将 return 对象 module,它有一个方法 __init__。但是这个方法只需要2个参数,你会得到一个错误。

import sys
type(sys).__init__(sys,2,3,4)
#Traceback (most recent call last):
#  File "testClassInheritance.py", line 11, in <module>
#    type(sys).__init__(sys,2,3,4)
#TypeError: module.__init__() takes at most 2 arguments (3 given)