【问题标题】:Is it possible to set a Metaclass globally so it applies to all classes created by default?是否可以全局设置元类,使其适用于默认创建的所有类?
【发布时间】:2020-06-28 01:00:53
【问题描述】:

我知道元类可以代替类型并定义新创建的类的行为方式。

例如:

class NoMixedCase(type):
   def __new__(cls,clsname,base,clsdict):
       for name in clsdict:
          if name.lower() != name:
              raise TypeError("Bad name.Don't mix case!")
       return super().__new__(cls,clsname,base,clsdict)

class Root(metaclass=NoMixedCase):
    pass

class B(Root):
    def Foo(self): #type error
        pass

但是,有没有一种全局设置 NoMixedCase 的方法,所以无论何时创建一个新类,它的行为默认由 NoMixedCase 定义,而不必从 Root 继承?

如果你这样做了......

Class B:  
    def Foo(self):
        pass

...它仍然会检查方法名称的大小写。

【问题讨论】:

  • import this显式优于隐式。指定metaclass=...有什么问题?
  • 这种问题应该由 linter 程序解决,可能使用自定义插件,并在 git 提交时通过提交钩子进行验证。
  • 今后,请始终使用通用 [python] 标签来解决所有与 python 相关的问题。自行决定使用特定于版本的标签。
  • 即使这是可能的,它也会破坏标准库和您所依赖的第 3 方库中的所有内容。

标签: python python-3.x class metaclass


【解决方案1】:

至于你的问题,不,它不是通常的——甚至可能不是一些特别的东西可以解决这个问题——很多 CPythons 内部的东西都与type 类相关联,并对其进行了硬编码.

在不立即使解释器崩溃的情况下,可以尝试为type.__new__ 编写一个包装器,并使用ctypes 直接在type.__new__ 插槽中替换它。 (普通作业做不到)。你可能仍然会崩溃。

因此,在现实生活中,如果您决定不按照我在上面的评论中建议的那样通过带有插件和提交钩子的 linter 程序,那么可行的方法是拥有一个使用您的元类的基类,并让您项目中的每个人都从该 Base 继承。

【讨论】:

    猜你喜欢
    • 2011-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多