当我阅读Python Cookbook 3rd Edition配方9.18时,我遇到了一个带有父类和一些可选参数的类定义,我查了一下。我知道 Python 3.6 为父类添加了__init_subclass__()
方法的新功能,但这本书是基于 Python 3.3 编写的,那么除了metaclass
之外,还有什么方法会接受这些参数呢?
类定义在这里:
class Spam(Base, debug=True, typecheck=False):
...
我知道元类可以在其__prepare__
、__new__
、__init__
方法中接受其他可选参数,但Base
父类,这些参数去哪儿了?
__init_subclass__
是对Python 3.6的补充,以减少对自定义元类的需求,因为它的许多用途都是"矫枉过正"。这个想法是为包含__init_subclass__
方法的(普通的,非元的(基类创建的每个子类,都将被调用,并将新的子类作为第一个参数:
class Base:
def __init_subclass__(subclass, debug=None, typecheck=None, **kwargs):
# do stuff with the optional debug and typecheck arguments
# Pass possible arguments not consumed here to superclasses, if any:
super().__init_subclass__(**kwargs)
并且根本不需要元类 - 默认元类的__prepare__
、__init__
和__new__
- type
- 将忽略以这种方式传递的任何命名参数。但是,如果未知的命名参数到达对象中的默认__init_subclass__
,则会引发它 - 上面的模式将使用这些参数,将它们从 kwargs 中删除。如果您正在处理未知的命名参数,只需像普通字典一样处理 kwargs - 无需在__init_subclass__
中使用显式命名参数。
他们像往常一样转到元类的__prepare__
方法。仅仅因为Base
没有指定元类并不意味着它没有元类。默认元类为 type
。
在 Python 3.6 中添加__init_subclass__
type
只是节省了您定义自定义元类的工作量,以便实现等效的__init_subclass__
自己。