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
Here are some additional ideas that might be useful when working with Python types.
4
+
5
+
## Using `Union` or `Optional` { #using-union-or-optional }
6
+
7
+
If your code for some reason can't use `|`, for example if it's not in a type annotation but in something like `response_model=`, instead of using the vertical bar (`|`) you can use `Union` from `typing`.
8
+
9
+
For example, you could declare that something could be a `str` or `None`:
10
+
11
+
```python
12
+
from typing import Union
13
+
14
+
15
+
defsay_hi(name: Union[str, None]):
16
+
print(f"Hi {name}!")
17
+
```
18
+
19
+
`typing` also has a shortcut to declare that something could be `None`, with `Optional`.
20
+
21
+
Here's a tip from my very **subjective** point of view:
22
+
23
+
* 🚨 Avoid using `Optional[SomeType]`
24
+
* Instead ✨ **use `Union[SomeType, None]`** ✨.
25
+
26
+
Both are equivalent and underneath they are the same, but I would recommend `Union` instead of `Optional` because the word "**optional**" would seem to imply that the value is optional, and it actually means "it can be `None`", even if it's not optional and is still required.
27
+
28
+
I think `Union[SomeType, None]` is more explicit about what it means.
29
+
30
+
It's just about the words and names. But those words can affect how you and your teammates think about the code.
31
+
32
+
As an example, let's take this function:
33
+
34
+
```python
35
+
from typing import Optional
36
+
37
+
38
+
defsay_hi(name: Optional[str]):
39
+
print(f"Hey {name}!")
40
+
```
41
+
42
+
The parameter `name` is defined as `Optional[str]`, but it is **not optional**, you cannot call the function without the parameter:
43
+
44
+
```Python
45
+
say_hi() # Oh, no, this throws an error! 😱
46
+
```
47
+
48
+
The `name` parameter is **still required** (not *optional*) because it doesn't have a default value. Still, `name` accepts `None` as the value:
49
+
50
+
```Python
51
+
say_hi(name=None) # This works, None is valid 🎉
52
+
```
53
+
54
+
The good news is, in most cases, you will be able to simply use `|` to define unions of types:
55
+
56
+
```python
57
+
defsay_hi(name: str|None):
58
+
print(f"Hey {name}!")
59
+
```
60
+
61
+
So, normally you don't have to worry about names like `Optional` and `Union`. 😎
### Generic types with type parameters { #generic-types-with-type-parameters }
138
+
### `typing` module { #typing-module }
139
139
140
-
There are some data structures that can contain other values, like `dict`, `list`, `set` and `tuple`. And the internal values can have their own type too.
140
+
For some additional use cases, you might need to import some things from the standard library `typing` module, for example when you want to declare that something has "any type", you can use `Any` from `typing`:
141
141
142
-
These types that have internal types are called "**generic**" types. And it's possible to declare them, even with their internal types.
142
+
```python
143
+
from typing import Any
143
144
144
-
To declare those types and the internal types, you can use the standard Python module `typing`. It exists specifically to support these type hints.
145
145
146
-
#### Newer versions of Python { #newer-versions-of-python }
147
-
148
-
The syntax using `typing` is **compatible** with all versions, from Python 3.6 to the latest ones, including Python 3.9, Python 3.10, etc.
146
+
defsome_function(data: Any):
147
+
print(data)
148
+
```
149
149
150
-
As Python advances, **newer versions** come with improved support for these type annotations and in many cases you won't even need to import and use the `typing` module to declare the type annotations.
150
+
### Generic types { #generic-types }
151
151
152
-
If you can choose a more recent version of Python for your project, you will be able to take advantage of that extra simplicity.
152
+
Some types can take "type parameters" in square brackets, to define their internal types, for example a "list of strings" would be declared `list[str]`.
153
153
154
-
In all the docs there are examples compatible with each version of Python (when there's a difference).
154
+
These types that can take type parameters are called **Generic types** or **Generics**.
155
155
156
-
For example "**Python 3.6+**" means it's compatible with Python 3.6 or above (including 3.7, 3.8, 3.9, 3.10, etc). And "**Python 3.9+**" means it's compatible with Python 3.9 or above (including 3.10, etc).
156
+
You can use the same builtin types as generics (with square brackets and types inside):
157
157
158
-
If you can use the **latest versions of Python**, use the examples for the latest version, those will have the **best and simplest syntax**, for example, "**Python 3.10+**".
158
+
*`list`
159
+
*`tuple`
160
+
*`set`
161
+
*`dict`
159
162
160
163
#### List { #list }
161
164
@@ -220,44 +223,20 @@ This means:
220
223
221
224
You can declare that a variable can be any of **several types**, for example, an `int` or a `str`.
222
225
223
-
In Python 3.6 and above (including Python 3.10) you can use the `Union` type from `typing` and put inside the square brackets the possible types to accept.
224
-
225
-
In Python 3.10 there's also a **new syntax** where you can put the possible types separated by a <dfntitle='also called "bitwise or operator", but that meaning is not relevant here'>vertical bar (`|`)</dfn>.
226
+
To define it you use the <dfntitle='also called "bitwise or operator", but that meaning is not relevant here'>vertical bar (`|`)</dfn> to separate both types.
226
227
227
-
//// tab | Python 3.10+
228
+
This is called a "union", because the variable can be anything in the union of those two sets of types.
Using `Optional[str]` instead of just `str` will let the editor help you detect errors where you could be assuming that a value is always a `str`, when it could actually be `None` too.
256
-
257
-
`Optional[Something]` is actually a shortcut for `Union[Something, None]`, they are equivalent.
258
-
259
-
This also means that in Python 3.10, you can use `Something | None`:
260
-
261
240
//// tab | Python 3.10+
262
241
263
242
```Python hl_lines="1"
@@ -266,96 +245,7 @@ This also means that in Python 3.10, you can use `Something | None`:
#### Using `Union` or `Optional` { #using-union-or-optional }
286
-
287
-
If you are using a Python version below 3.10, here's a tip from my very **subjective** point of view:
288
-
289
-
* 🚨 Avoid using `Optional[SomeType]`
290
-
* Instead ✨ **use `Union[SomeType, None]`** ✨.
291
-
292
-
Both are equivalent and underneath they are the same, but I would recommend `Union` instead of `Optional` because the word "**optional**" would seem to imply that the value is optional, and it actually means "it can be `None`", even if it's not optional and is still required.
293
-
294
-
I think `Union[SomeType, None]` is more explicit about what it means.
295
-
296
-
It's just about the words and names. But those words can affect how you and your teammates think about the code.
And then you won't have to worry about names like `Optional` and `Union`. 😎
319
-
320
-
#### Generic types { #generic-types }
321
-
322
-
These types that take type parameters in square brackets are called **Generic types** or **Generics**, for example:
323
-
324
-
//// tab | Python 3.10+
325
-
326
-
You can use the same builtin types as generics (with square brackets and types inside):
327
-
328
-
*`list`
329
-
*`tuple`
330
-
*`set`
331
-
*`dict`
332
-
333
-
And the same as with previous Python versions, from the `typing` module:
334
-
335
-
*`Union`
336
-
*`Optional`
337
-
* ...and others.
338
-
339
-
In Python 3.10, as an alternative to using the generics `Union` and `Optional`, you can use the <dfntitle='also called "bitwise or operator", but that meaning is not relevant here'>vertical bar (`|`)</dfn> to declare unions of types, that's a lot better and simpler.
340
-
341
-
////
342
-
343
-
//// tab | Python 3.9+
344
-
345
-
You can use the same builtin types as generics (with square brackets and types inside):
346
-
347
-
*`list`
348
-
*`tuple`
349
-
*`set`
350
-
*`dict`
351
-
352
-
And generics from the `typing` module:
353
-
354
-
*`Union`
355
-
*`Optional`
356
-
* ...and others.
357
-
358
-
////
248
+
Using `str | None` instead of just `str` will let the editor help you detect errors where you could be assuming that a value is always a `str`, when it could actually be `None` too.
359
249
360
250
### Classes as types { #classes-as-types }
361
251
@@ -403,17 +293,11 @@ To learn more about <a href="https://docs.pydantic.dev/" class="external-link" t
403
293
404
294
You will see a lot more of all this in practice in the [Tutorial - User Guide](tutorial/index.md){.internal-link target=_blank}.
405
295
406
-
/// tip
407
-
408
-
Pydantic has a special behavior when you use `Optional` or `Union[Something, None]` without a default value, you can read more about it in the Pydantic docs about <ahref="https://docs.pydantic.dev/2.3/usage/models/#required-fields"class="external-link"target="_blank">Required Optional fields</a>.
409
-
410
-
///
411
-
412
296
## Type Hints with Metadata Annotations { #type-hints-with-metadata-annotations }
413
297
414
298
Python also has a feature that allows putting **additional <dfntitle="Data about the data, in this case, information about the type, e.g. a description.">metadata</dfn>** in these type hints using `Annotated`.
415
299
416
-
Since Python 3.9,`Annotated` is a part of the standard library, so you can import it from `typing`.
Copy file name to clipboardExpand all lines: docs/en/docs/tutorial/body.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -155,7 +155,7 @@ The function parameters will be recognized as follows:
155
155
156
156
FastAPI will know that the value of `q` is not required because of the default value `= None`.
157
157
158
-
The `str | None`(Python 3.10+) or `Union` in `Union[str, None]` (Python 3.9+) is not used by FastAPI to determine that the value is not required, it will know it's not required because it has a default value of `= None`.
158
+
The `str | None` is not used by FastAPI to determine that the value is not required, it will know it's not required because it has a default value of `= None`.
159
159
160
160
But adding the type annotations will allow your editor to give you better support and detect errors.
0 commit comments