Optional[...]
là một ký hiệu viết tắt cho Union[..., None]
, cho người kiểm tra kiểu biết rằng một đối tượng của kiểu cụ thể là bắt buộc hoặc None
được yêu cầu. ...
là viết tắt của bất kỳ gợi ý loại hợp lệ nào , bao gồm các loại hợp chất phức tạp hoặc Union[]
nhiều loại hơn. Bất cứ khi nào bạn có một đối số từ khóa với giá trị mặc định None
, bạn nên sử dụng Optional
.
Vì vậy, đối với hai ví dụ của bạn, bạn có dict
và list
các loại vùng chứa, nhưng giá trị mặc định cho a
đối số từ khóa cho thấy điều đó None
cũng được phép, vì vậy hãy sử dụng Optional[...]
:
from typing import Optional
def test(a: Optional[dict] = None) -> None:
def test(a: Optional[list] = None) -> None:
Lưu ý rằng về mặt kỹ thuật không có sự khác biệt giữa việc sử dụng Optional[]
trên a Union[]
hoặc chỉ thêm None
vào Union[]
. Vì vậy Optional[Union[str, int]]
và Union[str, int, None]
chính xác là những điều giống nhau.
Cá nhân, tôi muốn sử dụng luôn luôn sử dụng Optional[]
khi đặt loại cho đối số từ khóa sử dụng = None
để đặt giá trị mặc định, điều này ghi lại lý do tại sao None
được cho phép tốt hơn. Hơn nữa, nó giúp dễ dàng di chuyển Union[...]
phần đó thành bí danh kiểu riêng biệt hoặc sau đó xóa Optional[...]
phần đó nếu một đối số trở nên bắt buộc.
Ví dụ, giả sử bạn có
from typing import Optional, Union
def api_function(optional_argument: Optional[Union[str, int]] = None) -> None:
"""Frob the fooznar.
If optional_argument is given, it must be an id of the fooznar subwidget
to filter on. The id should be a string, or for backwards compatibility,
an integer is also accepted.
"""
sau đó tài liệu được cải thiện bằng cách kéo Union[str, int]
bí danh thành một loại:
from typing import Optional, Union
SubWidgetId = Union[str, int]
def api_function(optional_argument: Optional[SubWidgetId] = None) -> None:
"""Frob the fooznar.
If optional_argument is given, it must be an id of the fooznar subwidget
to filter on. The id should be a string, or for backwards compatibility,
an integer is also accepted.
"""
Bộ tái cấu trúc để chuyển Union[]
thành bí danh trở nên dễ dàng hơn nhiều vì Optional[...]
đã được sử dụng thay vì Union[str, int, None]
. Các None
giá trị không phải là một 'id subwidget' sau khi tất cả, nó không phải là một phần của giá trị, None
có nghĩa là để cờ sự vắng mặt của một giá trị.
Lưu ý bên cạnh: Trừ khi mã của bạn chỉ phải hỗ trợ Python 3.9 hoặc mới hơn, bạn muốn tránh sử dụng các loại vùng chứa thư viện tiêu chuẩn trong gợi ý loại, vì bạn không thể nói bất kỳ điều gì về loại chúng phải chứa. Vì vậy, thay vì dict
và list
, sử dụng typing.Dict
và typing.List
, tương ứng. Và khi chỉ đọc từ một loại vùng chứa, bạn cũng có thể chấp nhận bất kỳ loại vùng chứa trừu tượng bất biến nào; danh sách và bộ giá trị là Sequence
các đối tượng, trong khi dict
là một Mapping
loại:
from typing import Mapping, Optional, Sequence, Union
def test(a: Optional[Mapping[str, int]] = None) -> None:
"""accepts an optional map with string keys and integer values"""
def test(a: Optional[Sequence[Union[int, str]]] = None) -> None:
"""accepts an optional sequence of integers and strings
# print(a) ==> [1, 2, 3, 4, 'a', 'b']
# or
# print(a) ==> None
Trong Python 3.9 trở lên, tất cả các loại vùng chứa tiêu chuẩn đều đã được cập nhật để hỗ trợ việc sử dụng chúng trong các gợi ý loại, hãy xem PEP 585 . Tuy nhiên , mặc dù bây giờ bạn có thể sử dụng dict[str, int]
hoặc list[Union[int, str]]
, bạn vẫn có thể muốn sử dụng các chú thích Mapping
và biểu cảm hơn Sequence
để chỉ ra rằng một hàm sẽ không thay đổi nội dung (chúng được coi là 'chỉ đọc') và các hàm sẽ hoạt động với bất kỳ đối tượng nào hoạt động dưới dạng ánh xạ hoặc chuỗi tương ứng.
Dict
vàList
từ nhập và viếtOptional[Dict]
vàOptional[List]
thay vìOptional[dict]
...