mirror of https://github.com/tiangolo/fastapi.git
📝 Add docs in Python Types for Optional (#1377)
* docs: Fix pydantic example in python-types.md
* 📝 Update Python Types Intro to include Optional
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
This commit is contained in:
parent
4a5cda0d77
commit
745ab48d65
|
|
@ -144,15 +144,15 @@ You can use, for example:
|
||||||
{!../../../docs_src/python_types/tutorial005.py!}
|
{!../../../docs_src/python_types/tutorial005.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Types with subtypes
|
### Generic types with type parameters
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
To declare those types and the subtypes, you can use the standard Python module `typing`.
|
To declare those types and the internal types, you can use the standard Python module `typing`.
|
||||||
|
|
||||||
It exists specifically to support these type hints.
|
It exists specifically to support these type hints.
|
||||||
|
|
||||||
#### Lists
|
#### `List`
|
||||||
|
|
||||||
For example, let's define a variable to be a `list` of `str`.
|
For example, let's define a variable to be a `list` of `str`.
|
||||||
|
|
||||||
|
|
@ -166,25 +166,30 @@ Declare the variable, with the same colon (`:`) syntax.
|
||||||
|
|
||||||
As the type, put the `List`.
|
As the type, put the `List`.
|
||||||
|
|
||||||
As the list is a type that takes a "subtype", you put the subtype in square brackets:
|
As the list is a type that contains some internal types, you put them in square brackets:
|
||||||
|
|
||||||
```Python hl_lines="4"
|
```Python hl_lines="4"
|
||||||
{!../../../docs_src/python_types/tutorial006.py!}
|
{!../../../docs_src/python_types/tutorial006.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
!!! tip
|
||||||
|
Those internal types in the square brackets are called "type parameters".
|
||||||
|
|
||||||
|
In this case, `str` is the type parameter passed to `List`.
|
||||||
|
|
||||||
That means: "the variable `items` is a `list`, and each of the items in this list is a `str`".
|
That means: "the variable `items` is a `list`, and each of the items in this list is a `str`".
|
||||||
|
|
||||||
By doing that, your editor can provide support even while processing items from the list.
|
By doing that, your editor can provide support even while processing items from the list:
|
||||||
|
|
||||||
Without types, that's almost impossible to achieve:
|
|
||||||
|
|
||||||
<img src="/img/python-types/image05.png">
|
<img src="/img/python-types/image05.png">
|
||||||
|
|
||||||
|
Without types, that's almost impossible to achieve.
|
||||||
|
|
||||||
Notice that the variable `item` is one of the elements in the list `items`.
|
Notice that the variable `item` is one of the elements in the list `items`.
|
||||||
|
|
||||||
And still, the editor knows it is a `str`, and provides support for that.
|
And still, the editor knows it is a `str`, and provides support for that.
|
||||||
|
|
||||||
#### Tuples and Sets
|
#### `Tuple` and `Set`
|
||||||
|
|
||||||
You would do the same to declare `tuple`s and `set`s:
|
You would do the same to declare `tuple`s and `set`s:
|
||||||
|
|
||||||
|
|
@ -197,13 +202,13 @@ This means:
|
||||||
* The variable `items_t` is a `tuple` with 3 items, an `int`, another `int`, and a `str`.
|
* The variable `items_t` is a `tuple` with 3 items, an `int`, another `int`, and a `str`.
|
||||||
* The variable `items_s` is a `set`, and each of its items is of type `bytes`.
|
* The variable `items_s` is a `set`, and each of its items is of type `bytes`.
|
||||||
|
|
||||||
#### Dicts
|
#### `Dict`
|
||||||
|
|
||||||
To define a `dict`, you pass 2 subtypes, separated by commas.
|
To define a `dict`, you pass 2 type parameters, separated by commas.
|
||||||
|
|
||||||
The first subtype is for the keys of the `dict`.
|
The first type parameter is for the keys of the `dict`.
|
||||||
|
|
||||||
The second subtype is for the values of the `dict`:
|
The second type parameter is for the values of the `dict`:
|
||||||
|
|
||||||
```Python hl_lines="1 4"
|
```Python hl_lines="1 4"
|
||||||
{!../../../docs_src/python_types/tutorial008.py!}
|
{!../../../docs_src/python_types/tutorial008.py!}
|
||||||
|
|
@ -215,6 +220,29 @@ This means:
|
||||||
* The keys of this `dict` are of type `str` (let's say, the name of each item).
|
* The keys of this `dict` are of type `str` (let's say, the name of each item).
|
||||||
* The values of this `dict` are of type `float` (let's say, the price of each item).
|
* The values of this `dict` are of type `float` (let's say, the price of each item).
|
||||||
|
|
||||||
|
#### `Optional`
|
||||||
|
|
||||||
|
You can also use `Optional` to declare that a variable has a type, like `str`, but that it is "optional", which means that it could also be `None`:
|
||||||
|
|
||||||
|
```Python hl_lines="1 4"
|
||||||
|
{!../../../docs_src/python_types/tutorial009.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
Using `Optional[str]` instead of just `str` will let the editor help you detecting errors where you could be assuming that a value is always a `str`, when it could actually be `None` too.
|
||||||
|
|
||||||
|
#### Generic types
|
||||||
|
|
||||||
|
These types that take type parameters in square brackets, like:
|
||||||
|
|
||||||
|
* `List`
|
||||||
|
* `Tuple`
|
||||||
|
* `Set`
|
||||||
|
* `Dict`
|
||||||
|
* `Optional`
|
||||||
|
* ...and others.
|
||||||
|
|
||||||
|
are called **Generic types** or **Generics**.
|
||||||
|
|
||||||
### Classes as types
|
### Classes as types
|
||||||
|
|
||||||
You can also declare a class as the type of a variable.
|
You can also declare a class as the type of a variable.
|
||||||
|
|
@ -222,13 +250,13 @@ You can also declare a class as the type of a variable.
|
||||||
Let's say you have a class `Person`, with a name:
|
Let's say you have a class `Person`, with a name:
|
||||||
|
|
||||||
```Python hl_lines="1 2 3"
|
```Python hl_lines="1 2 3"
|
||||||
{!../../../docs_src/python_types/tutorial009.py!}
|
{!../../../docs_src/python_types/tutorial010.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
Then you can declare a variable to be of type `Person`:
|
Then you can declare a variable to be of type `Person`:
|
||||||
|
|
||||||
```Python hl_lines="6"
|
```Python hl_lines="6"
|
||||||
{!../../../docs_src/python_types/tutorial009.py!}
|
{!../../../docs_src/python_types/tutorial010.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
And then, again, you get all the editor support:
|
And then, again, you get all the editor support:
|
||||||
|
|
@ -250,7 +278,7 @@ And you get all the editor support with that resulting object.
|
||||||
Taken from the official Pydantic docs:
|
Taken from the official Pydantic docs:
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!../../../docs_src/python_types/tutorial010.py!}
|
{!../../../docs_src/python_types/tutorial011.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! info
|
!!! info
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
class Person:
|
from typing import Optional
|
||||||
def __init__(self, name: str):
|
|
||||||
self.name = name
|
|
||||||
|
|
||||||
|
|
||||||
def get_person_name(one_person: Person):
|
def say_hi(name: Optional[str] = None):
|
||||||
return one_person.name
|
if name is not None:
|
||||||
|
print(f"Hey {name}!")
|
||||||
|
else:
|
||||||
|
print("Hello World")
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,7 @@
|
||||||
from datetime import datetime
|
class Person:
|
||||||
from typing import List
|
def __init__(self, name: str):
|
||||||
|
self.name = name
|
||||||
from pydantic import BaseModel
|
|
||||||
|
|
||||||
|
|
||||||
class User(BaseModel):
|
def get_person_name(one_person: Person):
|
||||||
id: int
|
return one_person.name
|
||||||
name = "John Doe"
|
|
||||||
signup_ts: datetime = None
|
|
||||||
friends: List[int] = []
|
|
||||||
|
|
||||||
|
|
||||||
external_data = {
|
|
||||||
"id": "123",
|
|
||||||
"signup_ts": "2017-06-01 12:22",
|
|
||||||
"friends": [1, "2", b"3"],
|
|
||||||
}
|
|
||||||
user = User(**external_data)
|
|
||||||
print(user)
|
|
||||||
# > User id=123 name='John Doe' signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3]
|
|
||||||
print(user.id)
|
|
||||||
# > 123
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
from datetime import datetime
|
||||||
|
from typing import List, Optional
|
||||||
|
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class User(BaseModel):
|
||||||
|
id: int
|
||||||
|
name = "John Doe"
|
||||||
|
signup_ts: Optional[datetime] = None
|
||||||
|
friends: List[int] = []
|
||||||
|
|
||||||
|
|
||||||
|
external_data = {
|
||||||
|
"id": "123",
|
||||||
|
"signup_ts": "2017-06-01 12:22",
|
||||||
|
"friends": [1, "2", b"3"],
|
||||||
|
}
|
||||||
|
user = User(**external_data)
|
||||||
|
print(user)
|
||||||
|
# > User id=123 name='John Doe' signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3]
|
||||||
|
print(user.id)
|
||||||
|
# > 123
|
||||||
Loading…
Reference in New Issue