CPython only makes these methods class method when a class created. If you set __class_getitem__ method after the creation it doesn't work unless you use classmethod decorator manually. >>> class B: ... pass ... >>> def y(*a, **k): ... return a, k ... >>> B.__class_getitem__ = y >>> B[int] ((<class 'int'>,), {}) >>> B.__class_getitem__ = classmethod(y) >>> B[int] ((<class '__main__.B'>, <class 'int'>), {})
Is this an issue though? Shouldn't methods be defined in the class definition, we don't expect setting a function as an attribute to a class to transform it automatically to a method. Why would we special case __class_getitem__ and not __init_subclass__?
> CPython only makes these methods class method when a class created. > If you set __class_getitem__ method after the creation it > doesn't work unless you use classmethod decorator manually. Give the intended use case for __class_getitem__ and that it was replacement for metaclass code with the same effect, the current behavior doesn't seem unreasonable. That said, I don't see any downside to allowing the method to attach after class creation. Assigning to Ivan to make the call on this one.
__new__ is special function too. It is converted as staticmethod when class creation. Since manually converting to (static|class)method is allowed, I don't think automatic conversion should be applied when attach after class creation. $ python3 Python 3.7.2 (default, Feb 12 2019, 08:15:36) [Clang 10.0.0 (clang-1000.11.45.5)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> class C: ... def __new__(cls): ... pass ... >>> type(C.__dict__['__new__']) <class 'staticmethod'> >>> class D: ... pass ... >>> D.__new__ = lambda cls: cls >>> type(D.__dict__['__new__']) <class 'function'>
I don't like complicating the code and adding a performance penalty to support such uncommon case. The documentation for __class_getitem__ precisely describes the current behavior: "when defined in the class body, this method is implicitly a class method". Nothing should be changed here. The documentation for __init_subclass__ could be rewritten in similar words.