Python继承、元类和type()函数

10

我不明白为什么以下代码会以特定的方式运行,具体情况如下:

from abc import ABCMeta   

class PackageClass(object):
    __metaclass__ = ABCMeta        

class MyClass1(PackageClass):
    pass

MyClass2 = type('MyClass2', (PackageClass, ), {})

print MyClass1
print MyClass2

>>> <class '__main__.MyClass1'> 
>>> <class 'abc.MyClass2'>

为什么repr(MyClass2)显示为abc.MyClass2(而事实并非如此)?

谢谢!


2
项目结构在这里似乎完全无关紧要。我建议删除该部分,只将其作为一个模块(所描述的行为仍然存在)。 - mgilson
@mgilson 谢谢你的注意,已经更新。 - Zaur Nasibov
1
另外,需要注意的是,这种行为在Python3.x中仍然存在(我刚测试过)。 - mgilson
@mgilson 在我的系统上不行 - 我使用 cpython 3.1、3.2 和 3.3,得到的是 <class '__main__.MyClass2'> - phihag
@phihag -- 你是否在使用Python3风格的元类?class PackageClass(metaclass = ABCMeta): pass - mgilson
3
更简单的测试案例:type('bar', (ABCMeta('foo', (object,), {}),), {})。这段代码会创建一个名为“bar”的类,并将其指定为一个由名为“foo”的抽象基类派生而来的类。 - nneonneo
1个回答

6
问题源于 ABCMeta 覆盖了 __new__ 并在其中调用了其超类构造函数(type())。type() 从其调用上下文中推导出新类的 __module__1;在这种情况下,type 调用似乎来自于 abc 模块。因此,新类的 __module__ 被设置为 abc(由于 type() 不知道实际的类构造发生在 __main__ 中)。
解决方法很简单,创建类型后只需自己设置 __module__ 即可:
MyClass2 = type('MyClass2', (PackageClass, ), {})
MyClass2.__module__ = __name__

我建议您提交一个错误报告。
相关:Base metaclass overriding __new__ generates classes with a wrong __module__Weird inheritance with metaclasses 1: type 是一个在C中定义的类型对象。它的新方法使用当前全局的__name__作为__module__,除非它调用元类构造函数。

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