注意:我只是将其作为答案,因为 ElmoVanKielmo 建议这样做。它绝对不应该是公认的答案,因为它只会让新手感到困惑……但也许对其他人来说会很有趣。
正如丹尼尔罗斯曼的回答所解释的那样,import Course
这意味着这Course
是一个模块,并且Course.Course
是您想要的课程。
那么,当您尝试从模块继承时会发生什么?
在 Python 中,类是对象,就像其他任何东西一样。一个类的类型(你可以通过打印出来看到type(AdvancedCourse)
)通常是type
,但是你可以通过设置一个元类来指定一个不同的类型。当你从一个超类继承时,如果你没有指定一个元类,你会得到你的超类的元类。所以,当你这样做时:
import Course
class AdvancedCourse(Course):
…你是说你的元类是type(Course)
——也就是说,module
.*
正如创建实例意味着调用类的 一样__init__
,创建类意味着调用元类的__init__
。参数,除此之外self
(这里是一个类,当然不是实例,因此通常命名cls
而不是self
)是类名、基类列表、方法字典和其他属性。所以,这个定义:
class AdvancedCourse(Course):
pass
... 尝试module
通过调用module.__init__(cls, 'AdvancedCourse', (Course,), {}
).**来初始化对象
当然模块也只是对象,所以它们也有一个__init__
,但它们的参数只是self
,名称和文档字符串。所以,你传递的参数太多了。
您实际上只是在这里走运;如果module
并且type
碰巧在它们的构造函数中采用相同数量的参数,你最终会得到一些非常奇怪的东西,在某些方面表现得有点像一个类,但在其他方面却不是,从而导致各种微妙的错误。
如果你想在交互式解释器中使用它,试试这个:
>>> class meta(type):
... def __init__(self, name, bases, d):
... print('{}\n{}\n{}\n{}\n'.format(self, name, bases, d))
... super(meta, self).__init__(name, bases, d)
>>> class Silly(metaclass=meta):
... __metaclass__=meta
<class '__main__.Silly'>
Silly
()
{'__module__': '__main__', '__qualname__': 'Silly', '__metaclass__': <class '__main__.meta'>}
>>> class Sillier(Silly):
... pass
<class '__main__.Sillier'>
Sillier
(<class '__main__.Silly'>,)
{'__module__': '__main__', '__qualname__': 'Sillier'}
在 Python 2.x 中,您不希望metaclass=meta
在类头中出现;你可以放在object
那里。在 3.x 中,您不需要__metaclass__=meta
在体内;你可以放在pass
那里。
*module
是内置函数中无法通过名称访问的“隐藏”类型之一,但您可以将其作为types.ModuleType
,或者仅通过导入某些内容并使用type(Course)
.
** 实际上,即使是一个空类,它的字典中也有几个成员。例如,在 Python 3.3 中,总是至少有一个__module__
属性和一个__qualname__
属性。