@@ -2180,22 +2180,142 @@ case the instance is itself a class.
21802180Emulating generic types
21812181-----------------------
21822182
2183- One can implement the generic class syntax as specified by :pep: `484 `
2184- (for example ``List[int] ``) by defining a special method:
2183+ When using :term: `type annotations<annotation> `, it is often useful to
2184+ *parameterize * a :term: `generic type ` using Python's square-brackets notation.
2185+ For example, the annotation ``list[int] `` might be used to signify a
2186+ :class: `list ` in which all the elements are of type :class: `int `.
2187+
2188+ .. seealso ::
2189+
2190+ :pep: `484 ` - Type Hints
2191+ Introducing Python's framework for type annotations
2192+
2193+ :ref: `Generic Alias Types<types-genericalias> `
2194+ Documentation for objects representing parameterized generic classes
2195+
2196+ :ref: `Generics `, :ref: `user-defined generics<user-defined-generics> ` and :class: `typing.Generic `
2197+ Documentation on how to implement generic classes that can be
2198+ parameterized at runtime and understood by static type-checkers.
2199+
2200+ A class can *generally * only be parameterized if it defines the special
2201+ class method ``__class_getitem__() ``.
21852202
21862203.. classmethod :: object.__class_getitem__(cls, key)
21872204
21882205 Return an object representing the specialization of a generic class
21892206 by type arguments found in *key *.
21902207
2191- This method is looked up on the class object itself, and when defined in
2192- the class body, this method is implicitly a class method. Note, this
2193- mechanism is primarily reserved for use with static type hints, other usage
2194- is discouraged.
2208+ When defined on a class, ``__class_getitem__() `` is automatically a class
2209+ method. As such, there is no need for it to be decorated with
2210+ :func: `@classmethod<classmethod> ` when it is defined.
21952211
2196- .. seealso ::
21972212
2198- :pep: `560 ` - Core support for typing module and generic types
2213+ The purpose of *__class_getitem__ *
2214+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2215+
2216+ The purpose of :meth: `~object.__class_getitem__ ` is to allow runtime
2217+ parameterization of standard-library generic classes in order to more easily
2218+ apply :term: `type hints<type hint> ` to these classes.
2219+
2220+ To implement custom generic classes that can be parameterized at runtime and
2221+ understood by static type-checkers, users should either inherit from a standard
2222+ library class that already implements :meth: `~object.__class_getitem__ `, or
2223+ inherit from :class: `typing.Generic `, which has its own implementation of
2224+ ``__class_getitem__() ``.
2225+
2226+ Custom implementations of :meth: `~object.__class_getitem__ ` on classes defined
2227+ outside of the standard library may not be understood by third-party
2228+ type-checkers such as mypy. Using ``__class_getitem__() `` on any class for
2229+ purposes other than type hinting is discouraged.
2230+
2231+
2232+ .. _classgetitem-versus-getitem :
2233+
2234+
2235+ *__class_getitem__ * versus *__getitem__ *
2236+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2237+
2238+ Usually, the :ref: `subscription<subscriptions> ` of an object using square
2239+ brackets will call the :meth: `~object.__getitem__ ` instance method defined on
2240+ the object's class. However, if the object being subscribed is itself a class,
2241+ the class method :meth: `~object.__class_getitem__ ` may be called instead.
2242+ ``__class_getitem__() `` should return a :ref: `GenericAlias<types-genericalias> `
2243+ object if it is properly defined.
2244+
2245+ Presented with the :term: `expression ` ``obj[x] ``, the Python interpreter
2246+ follows something like the following process to decide whether
2247+ :meth: `~object.__getitem__ ` or :meth: `~object.__class_getitem__ ` should be
2248+ called::
2249+
2250+ from inspect import isclass
2251+
2252+ def subscribe(obj, x):
2253+ """Return the result of the expression `obj[x]`"""
2254+
2255+ class_of_obj = type(obj)
2256+
2257+ # If the class of obj defines __getitem__,
2258+ # call class_of_obj.__getitem__(obj, x)
2259+ if hasattr(class_of_obj, '__getitem__'):
2260+ return class_of_obj.__getitem__(obj, x)
2261+
2262+ # Else, if obj is a class and defines __class_getitem__,
2263+ # call obj.__class_getitem__(x)
2264+ elif isclass(obj) and hasattr(obj, '__class_getitem__'):
2265+ return obj.__class_getitem__(x)
2266+
2267+ # Else, raise an exception
2268+ else:
2269+ raise TypeError(
2270+ f"'{class_of_obj.__name__}' object is not subscriptable"
2271+ )
2272+
2273+ In Python, all classes are themselves instances of other classes. The class of
2274+ a class is known as that class's :term: `metaclass `, and most classes have the
2275+ :class: `type ` class as their metaclass. :class: `type ` does not define
2276+ :meth: `~object.__getitem__ `, meaning that expressions such as ``list[int] ``,
2277+ ``dict[str, float] `` and ``tuple[str, bytes] `` all result in
2278+ :meth: `~object.__class_getitem__ ` being called::
2279+
2280+ >>> # list has class "type" as its metaclass, like most classes:
2281+ >>> type(list)
2282+ <class 'type'>
2283+ >>> type(dict) == type(list) == type(tuple) == type(str) == type(bytes)
2284+ True
2285+ >>> # "list[int]" calls "list.__class_getitem__(int)"
2286+ >>> list[int]
2287+ list[int]
2288+ >>> # list.__class_getitem__ returns a GenericAlias object:
2289+ >>> type(list[int])
2290+ <class 'types.GenericAlias'>
2291+
2292+ However, if a class has a custom metaclass that defines
2293+ :meth: `~object.__getitem__ `, subscribing the class may result in different
2294+ behaviour. An example of this can be found in the :mod: `enum ` module::
2295+
2296+ >>> from enum import Enum
2297+ >>> class Menu(Enum):
2298+ ... """A breakfast menu"""
2299+ ... SPAM = 'spam'
2300+ ... BACON = 'bacon'
2301+ ...
2302+ >>> # Enum classes have a custom metaclass:
2303+ >>> type(Menu)
2304+ <class 'enum.EnumMeta'>
2305+ >>> # EnumMeta defines __getitem__,
2306+ >>> # so __class_getitem__ is not called,
2307+ >>> # and the result is not a GenericAlias object:
2308+ >>> Menu['SPAM']
2309+ <Menu.SPAM: 'spam'>
2310+ >>> type(Menu['SPAM'])
2311+ <enum 'Menu'>
2312+
2313+
2314+ .. seealso ::
2315+ :pep: `560 ` - Core Support for typing module and generic types
2316+ Introducing :meth: `~object.__class_getitem__ `, and outlining when a
2317+ :ref: `subscription<subscriptions> ` results in ``__class_getitem__() ``
2318+ being called instead of :meth: `~object.__getitem__ `
21992319
22002320
22012321.. _callable-types :
@@ -2295,19 +2415,27 @@ through the object's keys; for sequences, it should iterate through the values.
22952415
22962416.. method :: object.__getitem__(self, key)
22972417
2298- Called to implement evaluation of ``self[key] ``. For sequence types, the
2299- accepted keys should be integers and slice objects. Note that the special
2300- interpretation of negative indexes (if the class wishes to emulate a sequence
2301- type) is up to the :meth: `__getitem__ ` method. If *key * is of an inappropriate
2302- type, :exc: `TypeError ` may be raised; if of a value outside the set of indexes
2303- for the sequence (after any special interpretation of negative values),
2304- :exc: `IndexError ` should be raised. For mapping types, if *key * is missing (not
2305- in the container), :exc: `KeyError ` should be raised.
2418+ Called to implement evaluation of ``self[key] ``. For :term: `sequence ` types,
2419+ the accepted keys should be integers and slice objects. Note that the
2420+ special interpretation of negative indexes (if the class wishes to emulate a
2421+ :term: `sequence ` type) is up to the :meth: `__getitem__ ` method. If *key * is
2422+ of an inappropriate type, :exc: `TypeError ` may be raised; if of a value
2423+ outside the set of indexes for the sequence (after any special
2424+ interpretation of negative values), :exc: `IndexError ` should be raised. For
2425+ :term: `mapping ` types, if *key * is missing (not in the container),
2426+ :exc: `KeyError ` should be raised.
2427+
2428+ .. note ::
2429+
2430+ :keyword: `for ` loops expect that an :exc: `IndexError ` will be raised for
2431+ illegal indexes to allow proper detection of the end of the sequence.
23062432
23072433 .. note ::
23082434
2309- :keyword: `for ` loops expect that an :exc: `IndexError ` will be raised for illegal
2310- indexes to allow proper detection of the end of the sequence.
2435+ When :ref: `subscripting<subscriptions> ` a *class *, the special
2436+ class method :meth: `~object.__class_getitem__ ` may be called instead of
2437+ ``__getitem__() ``. See :ref: `classgetitem-versus-getitem ` for more
2438+ details.
23112439
23122440
23132441.. method :: object.__setitem__(self, key, value)
0 commit comments