【问题标题】:subclass __module__ set to metaclass module when manually creating new class with type()使用 type() 手动创建新类时,子类 __module__ 设置为元类模块
【发布时间】:2018-09-02 14:09:17
【问题描述】:

在以下示例中,新创建的子类最终成为元类__module__,而不是父类的模块。我只在使用 ABCMeta 时看到过这种情况,所以它可能是该模块特有的,有人知道会发生什么吗?

In [1]: from abc import ABCMeta

In [2]: class test(metaclass=ABCMeta):
   ...:     pass
   ...: 

In [3]: newclass = type('newclass', (test,), {})

In [4]: newclass.__module__
Out[4]: 'abc'

当我以更标准的方式定义子类时会发生我想要的行为:

In [5]: class subtest(test):
   ...:     pass
   ...: 

In [6]: subtest.__module__
Out[6]: '__main__'

有人能解释一下为什么会出现这种情况,以及如何使用type 创建一个继承了正确__module__ 属性的新子类(例如__module__=='__main__')吗?

【问题讨论】:

  • 这看起来可能是一个实际的错误。很有趣。

标签: python python-3.x metaprogramming metaclass


【解决方案1】:

如果传递给type.__new__ 的映射中不存在__module__ 键,type.__new__ 根据调用type.__new__ 的模块确定__module__by looking for __name__ in the globals of the top Python stack frame

当您运行newclass = type('newclass', (test,), {}) 时,type 构造函数从abc 模块内部委托给abc.ABCMetawhich then calls type.__new__,因此type 认为__module__ 可能应该是abc

当你编写类语句时

class subtest(test):
    pass

class 语句的编译字节码自动包含一个__module__ = __name__ 赋值,它使用当前模块的__name__ 而不是abc.__name__

如果要控制直接调用type创建的类的__module__的值,可以在原映射中设置key,或者创建后赋值给类的__module__

newclass = type('newclass', (test,), {'__module__': __name__})

# or

newclass = type('newclass', (test,), {})
newclass.__module__ = __name__

【讨论】:

  • @wim。我想这并不比允许abc.ABCMeta 为您隐式设置更危险。
  • @wim。在 shell 中执行__name__ = 'asdfsdaasdasd',然后使用classtype 检查您创建的任何新类的__module__。有趣的东西。
  • @wim:答案已扩展。
  • 好,+1。您认为newclass 是否有任何可能的差异,这取决于它是否从传递给类型的命名空间接收__module__ 与之后设置它?
  • @wim:我认为typeabc.ABCMeta 不会有问题,但如果其他元类想在类型创建时使用__module__,它会在原始映射中需要__module__。此外,如果某些代码在创建它和重新分配其__module__ 之间以某种方式访问​​了类对象,则该代码可以看到__module__ 的原始值。
猜你喜欢
  • 2011-11-11
  • 2017-11-11
  • 2021-05-11
  • 2023-02-22
  • 1970-01-01
  • 2015-03-26
  • 2015-04-07
  • 2011-03-28
  • 1970-01-01
相关资源
最近更新 更多