@@ -256,11 +256,34 @@ method receives an integer we return a single item. If it receives a
256
256
``slice ``, we return a :py:class: `~typing.Sequence ` of items.
257
257
258
258
We can precisely encode this relationship between the argument and the
259
- return type by using overloads like so:
259
+ return type by using overloads like so (Python 3.12 syntax) :
260
260
261
261
.. code-block :: python
262
262
263
- from typing import Sequence, TypeVar, Union, overload
263
+ from collections.abc import Sequence
264
+ from typing import overload
265
+
266
+ class MyList[T](Sequence[T]):
267
+ @overload
268
+ def __getitem__ (self , index : int ) -> T: ...
269
+
270
+ @overload
271
+ def __getitem__ (self , index : slice ) -> Sequence[T]: ...
272
+
273
+ def __getitem__ (self , index : int | slice ) -> T | Sequence[T]:
274
+ if isinstance (index, int ):
275
+ # Return a T here
276
+ elif isinstance (index, slice ):
277
+ # Return a sequence of Ts here
278
+ else :
279
+ raise TypeError (... )
280
+
281
+ Here is the same example using the legacy syntax (Python 3.11 and earlier):
282
+
283
+ .. code-block :: python
284
+
285
+ from collections.abc import Sequence
286
+ from typing import TypeVar, Union, overload
264
287
265
288
T = TypeVar(' T' )
266
289
@@ -697,14 +720,13 @@ Restricted methods in generic classes
697
720
-------------------------------------
698
721
699
722
In generic classes some methods may be allowed to be called only
700
- for certain values of type arguments:
723
+ for certain values of type arguments (Python 3.12 syntax) :
701
724
702
725
.. code-block :: python
703
726
704
- T = TypeVar(' T' )
705
-
706
- class Tag (Generic[T]):
727
+ class Tag[T]:
707
728
item: T
729
+
708
730
def uppercase_item (self : Tag[str ]) -> str :
709
731
return self .item.upper()
710
732
@@ -714,18 +736,18 @@ for certain values of type arguments:
714
736
ts.uppercase_item() # This is OK
715
737
716
738
This pattern also allows matching on nested types in situations where the type
717
- argument is itself generic:
739
+ argument is itself generic (Python 3.12 syntax) :
718
740
719
741
.. code-block :: python
720
742
721
- T = TypeVar(' T' , covariant = True )
722
- S = TypeVar(' S' )
743
+ from collections.abc import Sequence
723
744
724
- class Storage (Generic [T]) :
745
+ class Storage[T]:
725
746
def __init__ (self , content : T) -> None :
726
- self .content = content
727
- def first_chunk (self : Storage[Sequence[S]]) -> S:
728
- return self .content[0 ]
747
+ self ._content = content
748
+
749
+ def first_chunk[S](self : Storage[Sequence[S]]) -> S:
750
+ return self ._content[0 ]
729
751
730
752
page: Storage[list[str ]]
731
753
page.first_chunk() # OK, type is "str"
@@ -734,13 +756,13 @@ argument is itself generic:
734
756
# "first_chunk" with type "Callable[[Storage[Sequence[S]]], S]"
735
757
736
758
Finally, one can use overloads on self-type to express precise types of
737
- some tricky methods:
759
+ some tricky methods (Python 3.12 syntax) :
738
760
739
761
.. code-block :: python
740
762
741
- T = TypeVar( ' T ' )
763
+ from typing import overload, Callable
742
764
743
- class Tag (Generic [T]) :
765
+ class Tag[T]:
744
766
@overload
745
767
def export (self : Tag[str ]) -> str : ...
746
768
@overload
@@ -799,23 +821,22 @@ Precise typing of alternative constructors
799
821
------------------------------------------
800
822
801
823
Some classes may define alternative constructors. If these
802
- classes are generic, self-type allows giving them precise signatures:
824
+ classes are generic, self-type allows giving them precise
825
+ signatures (Python 3.12 syntax):
803
826
804
827
.. code-block :: python
805
828
806
- T = TypeVar(' T' )
807
-
808
- class Base (Generic[T]):
809
- Q = TypeVar(' Q' , bound = ' Base[T]' )
829
+ from typing import Self
810
830
831
+ class Base[T]:
811
832
def __init__ (self , item : T) -> None :
812
833
self .item = item
813
834
814
835
@ classmethod
815
- def make_pair (cls : Type[Q] , item : T) -> tuple[Q, Q ]:
836
+ def make_pair (cls , item : T) -> tuple[Self, Self ]:
816
837
return cls (item), cls (item)
817
838
818
- class Sub (Base[T]):
839
+ class Sub[T] (Base[T]):
819
840
...
820
841
821
842
pair = Sub.make_pair(' yes' ) # Type is "tuple[Sub[str], Sub[str]]"
0 commit comments