You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -25,13 +25,13 @@ Today, type hints are essential for modern Python development. They significantl
25
25
26
26
## typing module vs collections module
27
27
28
-
Since Python 3.9, most of types in `typing` module is[deprecated](https://docs.python.org/3/library/typing.html#deprecated-aliases), and `collections` module is recommended.
28
+
Since Python 3.9, most of types in `typing` module i[deprecated](https://docs.python.org/3/library/typing.html#deprecated-aliases), and `collections` module is recommended.
29
29
30
30
Some types like: `typing.Any`, `typing.Generic`, `typing.TypeVar`, etc. are still not deprecated.
31
31
32
32
!!! note "Thanks to subscription support in many collections since Python3.9"
33
33
The `collections` module is now the preferred way to import many types (not all yet), as [they support subscription at runtime](https://mypy.readthedocs.io/en/stable/runtime_troubles.html#using-generic-builtins). [Subscription](https://docs.python.org/3/reference/expressions.html#subscriptions) refers to using square brackets `[]` to indicate the type of elements in a collection. **Subscription at runtime** means we can use `list[int]`, `dict[str, int]`, etc. directly without importing from `typing.List`, `typing.Dict`, etc.
@@ -163,58 +163,57 @@ Some types like: `typing.Any`, `typing.Generic`, `typing.TypeVar`, etc. are stil
163
163
[From Mypy](https://mypy.readthedocs.io/en/stable/kinds_of_types.html#type-aliases): Python 3.12 introduced the `type` statement for defining explicit type aliases. Explicit type aliases are unambiguous and can also improve readability by making the intent clear.
164
164
The definition may contain forward references without having to use string literal escaping, **since it is evaluated lazily**, which improves also the loading performance.
165
165
166
-
```python
167
-
type AliasType = list[dict[tuple[int, str], set[int]]] | tuple[str, list[str]]
166
+
```python
167
+
type AliasType = list[dict[tuple[int, str], set[int]]] | tuple[str, list[str]]
168
168
169
-
# Now we can use AliasType in place of the full name:
169
+
# Now we can use AliasType in place of the full name:
170
170
171
-
def f() -> AliasType:
172
-
...
173
-
```
171
+
deff() -> AliasType:
172
+
...
173
+
```
174
174
175
175
## Type variable
176
176
177
177
[From MyPy](https://mypy.readthedocs.io/en/stable/kinds_of_types.html#the-type-of-class-objects): Python 3.12 introduced new syntax to use the `type[C]` and a type variable with an upper bound (see [Type variables with upper bounds](https://mypy.readthedocs.io/en/stable/generics.html#type-variable-upper-bound)).
178
178
179
-
```python title="Python 3.12 syntax"
180
-
def new_user[U: User](user_class: type[U]) -> U:
181
-
# Same implementation as before
182
-
```
179
+
```python title="Python 3.12 syntax"
180
+
def new_user[U: User](user_class: type[U]) -> U:
181
+
# Same implementation as before
182
+
```
183
183
184
184
Here is the example using the legacy syntax (**Python 3.11 and earlier**):
185
185
186
-
```python title="Python 3.11 and earlier syntax"
187
-
U = TypeVar('U', bound=User)
186
+
```python title="Python 3.11 and earlier syntax"
187
+
U = TypeVar('U', bound=User)
188
188
189
-
def new_user(user_class: type[U]) -> U:
190
-
# Same implementation as before
191
-
```
189
+
defnew_user(user_class: type[U]) -> U:
190
+
# Same implementation as before
191
+
```
192
192
193
193
Now mypy will infer the correct type of the result when we call new_user() with a specific subclass of User:
194
194
195
-
```python
196
-
beginner = new_user(BasicUser) # Inferred type is BasicUser
197
-
beginner.upgrade() # OK
198
-
199
-
```
195
+
```python
196
+
beginner = new_user(BasicUser) # Inferred type is BasicUser
197
+
beginner.upgrade() # OK
198
+
```
200
199
201
200
## Annotating \_\_init\_\_ methods
202
201
203
202
[From MyPy](https://mypy.readthedocs.io/en/stable/class_basics.html#annotating-init-methods): It is allowed to omit the return type declaration on \_\_init\_\_ methods if at least one argument is annotated.
204
203
205
-
```python
206
-
class C1:
207
-
# __init__ has no argument is annotated,
208
-
# so we should add return type declaration
209
-
def __init__(self) -> None:
210
-
self.var = 42
204
+
```python
205
+
classC1:
206
+
# __init__ has no argument is annotated,
207
+
# so we should add return type declaration
208
+
def__init__(self) -> None:
209
+
self.var =42
211
210
212
-
class C2:
213
-
# __init__ has at least one argument is annotated,
214
-
# so it's allowed to omit the return type declaration
215
-
# so in most cases, we don't need to add return type.
216
-
def __init__(self, arg: int):
217
-
self.var = arg
211
+
classC2:
212
+
# __init__ has at least one argument is annotated,
213
+
# so it's allowed to omit the return type declaration
214
+
# so in most cases, we don't need to add return type.
215
+
def__init__(self, arg: int):
216
+
self.var = arg
218
217
219
218
```
220
219
@@ -228,18 +227,18 @@ Now mypy will infer the correct type of the result when we call new_user() with
228
227
229
228
`from __future__ import annotations`**must be the first executable line** in the file. You can only have shebang and comment lines before it.
230
229
231
-
```python hl_lines="1 7"
232
-
from __future__ import annotations
233
-
from pydantic import BaseModel
230
+
```python hl_lines="1 7"
231
+
from__future__import annotations
232
+
from pydantic import BaseModel
234
233
235
-
class User(BaseModel):
236
-
name: str
237
-
age: int
238
-
friends: list[User] = [] # Forward reference works
234
+
classUser(BaseModel):
235
+
name: str
236
+
age: int
237
+
friends: list[User] = [] # Forward reference works
239
238
240
-
# This works in Pydantic v2
241
-
user = User(name="Alice", age=30, friends=[])
242
-
```
239
+
# This works in Pydantic v2
240
+
user = User(name="Alice", age=30, friends=[])
241
+
```
243
242
244
243
!!! warning "from \_\_future\_\_ import annotation is not fully compatible with Pydantic"
245
244
See this [warning](https://mypy.readthedocs.io/en/stable/runtime_troubles.html#future-annotations-import-pep-563), and see this [github issue](https://github.com/jlowin/fastmcp/issues/905), and [this issue](https://github.com/pydantic/pydantic/issues/2678) for the compatibility issues with Pydantic and postponed evaluation of annotations.
@@ -250,57 +249,57 @@ Now mypy will infer the correct type of the result when we call new_user() with
250
249
251
250
[From MyPy](https://mypy.readthedocs.io/en/stable/runtime_troubles.html#import-cycles): If the cycle import is only needed for type annotations:
SqlAlchemy also uses [string literal](https://mypy.readthedocs.io/en/stable/runtime_troubles.html#string-literal-types-and-type-comments) for lazy evaluation and [typing.TYPE_CHECKING](https://mypy.readthedocs.io/en/stable/runtime_troubles.html#typing-type-checking) for typing:
0 commit comments