显然,在元类中的__new__
在实例化元类即类对象时运行,因此元类中的__new__
提供了一个钩子来拦截在类定义时间(例如验证/强制执行类属性(如方法)的规则)运行的事件(/代码)。
许多在线示例中,元类中的__new__
返回类型构造函数的实例,这似乎有些问题,因为这会阻止__init__
(文档:“如果__new__()
不返回cls的实例,则新实例的__init__()
方法不会被调用”)。
当尝试使用元类中的__new__
的返回值时,我遇到了一些奇怪的情况,其中有些我并不完全理解,例如:
class Meta(type):
def __new__(self, name, bases, attrs):
print("Meta __new__ running!")
# return type(name, bases, attrs) # 1.
# return super().__new__(self, name, bases, attrs) # 2.
# return super().__new__(name, bases, attrs) # 3.
# return super().__new__(type, name, bases, attrs) # 4.
# return self(name, bases, attrs) # 5.
def __init__(self, *args, **kwargs):
print("Meta __init__ running!")
return super().__init__(*args, **kwargs)
class Cls(metaclass=Meta):
pass
- 这经常在例子中看到,通常可行,但会阻止
__init__
。 - 这样可以工作,并且
__init__
也会触发;但是为什么要在super()调用中传递self?难道不应该自动通过super()传递self/cls吗? - 这引发了一个我无法理解的奇怪错误:TypeError:
type.__new__(X)
:X不是类型对象(str);这里的X是什么?难道self不应该自动传递吗? - 3.的错误启发我尝试传递type直接作为super()调用的第一个参数;这也会阻止
__init__
。这里发生了什么? - 仅出于好玩尝试;这导致了RecursionError。
特别是案例1和2似乎对继承绑定到元类的类有深远的影响:
class LowerCaseEnforcer(type):
""" Allows only lower case names as class attributes! """
def __new__(self, name, bases, attrs):
for name in attrs:
if name.lower() != name:
raise TypeError(f"Inappropriate method name: {name}")
# return type(name, bases, attrs) # 1.
# return super().__new__(self, name, bases, attrs) # 2.
class Super(metaclass=LowerCaseEnforcer):
pass
class Sub(Super):
def some_method(self):
pass
## this will error in case 2 but not case 1
def Another_method(self):
pass
- 预期行为:元类绑定到超类,但不绑定到子类
- 将超类和子类绑定到元类;?
如果有人能缓慢、友善地解释上述示例中正在发生的事情,我会非常感激!:D