Kiểu chữ python

Các kiểu chữ cho phép bạn chỉ ra rằng một biểu thức bằng một số giá trị nguyên thủy cụ thể. Ví dụ ta chú thích biến kiểu

a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
6 thì mypy sẽ hiểu biến đó không chỉ kiểu
a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
7 mà còn bằng cụ thể là chuỗi
a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
8

Tính năng này chủ yếu hữu ích khi chú thích các chức năng hoạt động khác nhau dựa trên giá trị chính xác mà người gọi cung cấp. Ví dụ: giả sử chúng ta có một hàm

a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
9 trả về
b = 19
reveal_type[b]          # Revealed type is "int"
0 nếu đối số đầu tiên là
b = 19
reveal_type[b]          # Revealed type is "int"
1 và
a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
7 nếu đó là
b = 19
reveal_type[b]          # Revealed type is "int"
3. Chúng ta có thể xây dựng một chữ ký kiểu chính xác cho chức năng này bằng cách sử dụng
b = 19
reveal_type[b]          # Revealed type is "int"
4 và quá tải

from typing import overload, Union, Literal

# The first two overloads use Literal[...] so we can
# have precise return types:

@overload
def fetch_data[raw: Literal[True]] -> bytes: ...
@overload
def fetch_data[raw: Literal[False]] -> str: ...

# The last overload is a fallback in case the caller
# provides a regular bool:

@overload
def fetch_data[raw: bool] -> Union[bytes, str]: ...

def fetch_data[raw: bool] -> Union[bytes, str]:
    # Implementation is omitted
    ...

reveal_type[fetch_data[True]]        # Revealed type is "bytes"
reveal_type[fetch_data[False]]       # Revealed type is "str"

# Variables declared without annotations will continue to have an
# inferred type of 'bool'.

variable = True
reveal_type[fetch_data[variable]]    # Revealed type is "Union[bytes, str]"

Ghi chú

Các ví dụ trong trang này nhập

b = 19
reveal_type[b]          # Revealed type is "int"
5 cũng như
b = 19
reveal_type[b]          # Revealed type is "int"
6 và
b = 19
reveal_type[b]          # Revealed type is "int"
7 từ mô-đun
b = 19
reveal_type[b]          # Revealed type is "int"
8. Các loại này đã được thêm vào
b = 19
reveal_type[b]          # Revealed type is "int"
8 trong Python 3. 8, nhưng cũng có sẵn để sử dụng trong Python 3. 4 - 3. 7 qua gói
a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
50

Tham số hóa Literals#

Các loại chữ có thể chứa một hoặc nhiều giá trị bool, int, str, byte và enum theo nghĩa đen. Tuy nhiên, các kiểu chữ không thể chứa các biểu thức tùy ý. các loại như

a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
51,
a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
52 hoặc
a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
53 đều là bất hợp pháp

Các chữ chứa hai hoặc nhiều giá trị tương đương với sự kết hợp của các giá trị đó. Vì vậy,

a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
54 tương đương với
a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
55. Điều này làm cho việc viết các loại phức tạp hơn liên quan đến chữ thuận tiện hơn một chút

Các loại chữ cũng có thể chứa

a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
56. Mypy sẽ coi
a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
57 tương đương với chỉ
a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
56. Điều này có nghĩa là
a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
59,
a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
50 và
a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
51 đều tương đương

Chữ cũng có thể chứa bí danh cho các loại chữ khác. Ví dụ, chương trình sau đây là hợp pháp

a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
7

Chữ có thể không chứa bất kỳ loại hoặc biểu thức nào khác. Điều này có nghĩa là làm

a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
52,
a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
53,
a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
54 hoặc
a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
55 đều là bất hợp pháp

Khai báo các biến số#

Bạn phải thêm một chú thích vào một biến một cách rõ ràng để khai báo rằng nó có kiểu chữ

a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"

Để duy trì khả năng tương thích ngược, các biến không có chú thích này không được coi là theo nghĩa đen

b = 19
reveal_type[b]          # Revealed type is "int"

Nếu bạn thấy việc lặp lại giá trị của biến trong gợi ý kiểu là tẻ nhạt, thay vào đó, bạn có thể thay đổi biến thành

b = 19
reveal_type[b]          # Revealed type is "int"
6 [xem Tên cuối cùng, phương thức và lớp]:

a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
5

Nếu bạn không cung cấp loại rõ ràng trong

b = 19
reveal_type[b]          # Revealed type is "int"
6, loại
a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
58 sẽ trở nên nhạy cảm với ngữ cảnh. mypy về cơ bản sẽ thử "thay thế" giá trị được gán ban đầu bất cứ khi nào nó được sử dụng trước khi thực hiện kiểm tra loại. Đây là lý do tại sao loại
a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
58 được tiết lộ là
a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
90. dấu chấm hỏi ở cuối phản ánh bản chất nhạy cảm với ngữ cảnh này

Ví dụ, mypy sẽ gõ kiểm tra chương trình trên gần giống như nó được viết như vậy

a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
5

Điều này có nghĩa là trong khi thay đổi một biến thành

b = 19
reveal_type[b]          # Revealed type is "int"
6 không hoàn toàn giống với việc thêm một chú thích rõ ràng
b = 19
reveal_type[b]          # Revealed type is "int"
4, nó thường dẫn đến tác dụng tương tự trong thực tế

Các trường hợp chính mà hành vi của các loại nhạy cảm theo ngữ cảnh và các loại theo nghĩa đen thực sự khác nhau là khi bạn thử sử dụng các loại đó ở những nơi không mong đợi một cách rõ ràng một

b = 19
reveal_type[b]          # Revealed type is "int"
4. Ví dụ: so sánh và đối chiếu điều gì sẽ xảy ra khi bạn thử thêm các loại này vào danh sách

a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
9

Lập chỉ mục thông minh#

Chúng ta có thể sử dụng các loại Literal để lập chỉ mục chính xác hơn thành các loại không đồng nhất có cấu trúc, chẳng hạn như bộ dữ liệu, NamedTuples và TypedDicts. Tính năng này được gọi là lập chỉ mục thông minh

Ví dụ: khi chúng tôi lập chỉ mục vào một bộ bằng cách sử dụng một số int, loại được suy ra thường là sự kết hợp của các loại mục bộ. Tuy nhiên, nếu chúng ta chỉ muốn loại tương ứng với một số chỉ mục cụ thể, chúng ta có thể sử dụng các loại Chữ như vậy

b = 19
reveal_type[b]          # Revealed type is "int"
5

công đoàn được gắn thẻ #

Khi bạn có một liên kết các loại, thông thường bạn có thể phân biệt giữa từng loại trong liên kết bằng cách sử dụng kiểm tra

a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
94. Ví dụ: nếu bạn có một biến
a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
95 thuộc loại
a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
96, bạn có thể viết một số mã chỉ chạy nếu
a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
95 là một số nguyên bằng cách thực hiện
a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
98

Tuy nhiên, không phải lúc nào cũng có thể hoặc thuận tiện để làm điều này. Ví dụ: không thể sử dụng

a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
94 để phân biệt giữa hai TypedDicts khác nhau vì khi chạy, biến của bạn sẽ chỉ là một lệnh

Thay vào đó, những gì bạn có thể làm là gắn nhãn hoặc gắn thẻ TypedDicts của mình bằng một loại Chữ riêng biệt. Sau đó, bạn có thể phân biệt giữa từng loại TypedDict bằng cách kiểm tra nhãn

b = 19
reveal_type[b]          # Revealed type is "int"
2

Mặc dù tính năng này chủ yếu hữu ích khi làm việc với TypedDicts, nhưng bạn cũng có thể sử dụng kỹ thuật tương tự với các đối tượng thông thường, bộ dữ liệu hoặc bộ dữ liệu có tên

Tương tự, các thẻ không cần phải cụ thể str Literals. chúng có thể là bất kỳ loại nào mà bạn thường có thể thu hẹp trong các câu lệnh

b = 19
reveal_type[b]          # Revealed type is "int"
50 và tương tự. Ví dụ: bạn có thể có các thẻ của mình là int hoặc Enum Literals hoặc thậm chí các lớp thông thường mà bạn thu hẹp bằng cách sử dụng
b = 19
reveal_type[b]          # Revealed type is "int"
51

b = 19
reveal_type[b]          # Revealed type is "int"
5

Tính năng này đôi khi được gọi là "loại tổng" hoặc "loại kết hợp phân biệt đối xử" trong các ngôn ngữ lập trình khác

Kiểm tra toàn diện#

Bạn có thể muốn kiểm tra xem một số mã bao gồm tất cả các trường hợp

b = 19
reveal_type[b]          # Revealed type is "int"
5 hoặc
b = 19
reveal_type[b]          # Revealed type is "int"
53 có thể xảy ra. Ví dụ

a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
70

Trong đoạn mã trên, rất dễ mắc lỗi. Bạn có thể thêm một giá trị bằng chữ mới vào

b = 19
reveal_type[b]          # Revealed type is "int"
54 nhưng quên xử lý nó trong hàm
b = 19
reveal_type[b]          # Revealed type is "int"
55

a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
71

Mypy sẽ không bắt được rằng

b = 19
reveal_type[b]          # Revealed type is "int"
56 không được bảo hiểm. Nếu bạn muốn mypy thực hiện kiểm tra toàn diện, bạn cần cập nhật mã của mình để sử dụng kiểm tra
b = 19
reveal_type[b]          # Revealed type is "int"
57

a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
72

Bây giờ nếu bạn thêm một giá trị mới vào

b = 19
reveal_type[b]          # Revealed type is "int"
54 nhưng không cập nhật
b = 19
reveal_type[b]          # Revealed type is "int"
55, mypy sẽ phát hiện ra lỗi

a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
73

Nếu không cần kiểm tra thời gian chạy đối với các giá trị không mong muốn, bạn có thể bỏ qua lệnh gọi

b = 19
reveal_type[b]          # Revealed type is "int"
20 trong ví dụ trên và mypy vẫn sẽ tạo ra lỗi về hàm
b = 19
reveal_type[b]          # Revealed type is "int"
55 trả về mà không có giá trị

a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
74

Kiểm tra tính toàn diện cũng được hỗ trợ cho các câu lệnh so khớp [Python 3. 10 trở lên]

a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
75

Hạn chế #

Mypy sẽ không hiểu các biểu thức sử dụng các biến loại

b = 19
reveal_type[b]          # Revealed type is "int"
22 ở mức độ sâu. Ví dụ: nếu bạn có một biến
b = 19
reveal_type[b]          # Revealed type is "int"
23 thuộc loại
b = 19
reveal_type[b]          # Revealed type is "int"
24 và một biến khác là
b = 19
reveal_type[b]          # Revealed type is "int"
25 thuộc loại
b = 19
reveal_type[b]          # Revealed type is "int"
26, mypy sẽ suy ra rằng
b = 19
reveal_type[b]          # Revealed type is "int"
27 thuộc loại
b = 19
reveal_type[b]          # Revealed type is "int"
28, không phải loại
b = 19
reveal_type[b]          # Revealed type is "int"
29

Quy tắc cơ bản là các kiểu chữ chỉ được coi là kiểu con thông thường của bất kỳ kiểu nào mà tham số có. Ví dụ:

b = 19
reveal_type[b]          # Revealed type is "int"
24 được coi là một kiểu con của
b = 19
reveal_type[b]          # Revealed type is "int"
28 và do đó sẽ kế thừa trực tiếp tất cả các phương thức của
b = 19
reveal_type[b]          # Revealed type is "int"
28. Điều này có nghĩa là
b = 19
reveal_type[b]          # Revealed type is "int"
53 chấp nhận các đối số giống nhau và có cùng kiểu trả về như
b = 19
reveal_type[b]          # Revealed type is "int"
54

Enums#

Mypy có hỗ trợ đặc biệt cho

b = 19
reveal_type[b]          # Revealed type is "int"
55 và các lớp con của nó.
b = 19
reveal_type[b]          # Revealed type is "int"
56,
b = 19
reveal_type[b]          # Revealed type is "int"
57,
b = 19
reveal_type[b]          # Revealed type is "int"
58 và
b = 19
reveal_type[b]          # Revealed type is "int"
59

a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
76

Bạn có thể sử dụng enums để chú thích các loại như bạn mong đợi

a: Literal[19] = 19
reveal_type[a]          # Revealed type is "Literal[19]"
77

Kiểm tra toàn diện#

Tương tự như các loại

b = 19
reveal_type[b]          # Revealed type is "int"
5,
b = 19
reveal_type[b]          # Revealed type is "int"
53 hỗ trợ kiểm tra tính toàn diện. Hãy bắt đầu với một định nghĩa

Chủ Đề