为何要将__init_subclass__中的cls设为仅限位置参数?
关于__init_subclass__中使用仅限位置参数(/)的疑问解答
先看PEP-0487里给出的__init_subclass__示例代码:
class Philosopher: def __init_subclass__(cls, /, default_name, **kwargs): super().__init_subclass__(**kwargs) cls.default_name = default_name class AustralianPhilosopher(Philosopher, default_name="Bruce"): pass
为什么__init_subclass__要使用/标记仅限位置参数?
__init_subclass__是Python自动触发的钩子:当你定义子类继承某个父类时,父类的__init_subclass__会被自动调用,第一个参数cls是解释器自动传入的子类本身——你完全不需要手动传递这个参数。
这里用/把cls标记为仅限位置参数,核心目的是语法层面的明确性,而非防范恶意使用:
- 它清晰地告诉开发者:
cls这个参数只能由解释器按位置注入,你既不需要传,也不能用关键字参数的形式去传(比如写Philosopher(cls=SomeClass))。 - 如果不标记,理论上有人可能错误地尝试传递
cls关键字参数,这会直接干扰解释器的自动注入逻辑,导致代码报错或行为异常。这和“成年人原则”不冲突——Python相信你不会故意乱传,但语法上的约束能帮你避免无心的错误。
是否所有带cls/self的类方法都要加/?
完全不需要。
普通实例方法的self、类方法的cls,虽然也是解释器自动传入,但它们的调用场景和__init_subclass__不同:
- 比如调用实例方法时,你只会写
obj.do_something(),不会去写obj.do_something(self=obj)——这种写法语法上允许,但没人会这么用,也不会带来实际的逻辑混乱。 - 而__init_subclass__的调用是在子类定义阶段,用户需要传递的是像示例里
default_name这类自定义关键字参数,此时如果不把cls设为仅限位置,很容易让开发者混淆哪些参数是自己该传的,哪些是解释器管的。所以这个/是针对__init_subclass__的特殊调用场景设计的,不是通用规则。
内容的提问来源于stack exchange,提问作者Jason S
相关产品推荐
相关产品推荐

