Trong bài học này, bạn sẽ tìm hiểu về các loại chính xác hơn trong Python 3. 8. Hệ thống gõ của Python đã khá trưởng thành vào thời điểm này. Tuy nhiên, trong Python 3. 8, một số tính năng mới đã được thêm vào gõ để cho phép gõ chính xác hơn
- các loại chữ
- từ điển đánh máy
- đối tượng cuối cùng
- giao thức
Python hỗ trợ các gợi ý loại tùy chọn, thường là chú thích trên mã của bạn
>>>
>>> def double[number: float] -> float:
.. return 2 * number
Trong ví dụ này, bạn nói rằng
$ python -m pip install mypy
3 phải là số float và $ python -m pip install mypy
4 cũng phải trả về số float. Tuy nhiên, Python coi những chú thích này là gợi ý. Chúng không được thi hành trong thời gian chạy>>>
>>> double[3.14]
6.28
>>> double["I'm not a float"]
"I'm not a floatI'm not a float"
$ python -m pip install mypy
4 vui vẻ chấp nhận $ python -m pip install mypy
6 như một đối số, mặc dù đó không phải là một sự thả nổiGợi ý nhập cho phép kiểm tra kiểu mã Python của bạn mà không thực sự chạy tập lệnh của bạn. Điều này gợi nhớ đến việc các trình biên dịch bắt lỗi kiểu trong các ngôn ngữ khác như Java và Rust. Ngoài ra, gợi ý nhập đóng vai trò là tài liệu về mã của bạn, giúp dễ đọc hơn cũng như
Ghi chú. Có sẵn một số trình kiểm tra kiểu tĩnh, bao gồm Pyright, Pytype và Pyre. Trong khóa học này, bạn sẽ sử dụng Mypy. Bạn có thể cài đặt Mypy từ PyPI bằng pip
$ python -m pip install mypy
Hãy thử Mypy trên ví dụ mã từ trước. Tạo một tệp mới có tên
$ python -m pip install mypy
7________số 8
Bây giờ hãy chạy Mypy trên mã này
$ mypy float_check.py
float_check.py:8: error: Argument 1 to "double" has incompatible
type "str"; expected "float"
Found 1 error in 1 file [checked 1 source file]
Dựa trên các gợi ý về loại, Mypy có thể cho bạn biết rằng bạn đang sử dụng loại sai trên dòng 8. Thay đổi đối số cho lệnh gọi thứ hai thành
$ python -m pip install mypy
4 thành $ python -m pip install mypy
9$ python -m pip install mypy
2Bây giờ hãy chạy lại Mypy trên mã này
$ python -m pip install mypy
3Theo một nghĩa nào đó, Mypy là triển khai tham chiếu của trình kiểm tra kiểu cho Python và đang được phát triển tại Dropbox dưới sự lãnh đạo của Jukka Lehtasalo. Người tạo ra Python, Guido van Rossum, là thành viên của nhóm Mypy
Bạn có thể tìm thêm thông tin về gợi ý kiểu trong Python trong PEP 484 gốc, cũng như trong Kiểm tra kiểu Python [Hướng dẫn] và khóa học video Kiểm tra kiểu Python
Có bốn PEP mới về kiểm tra kiểu đã được chấp nhận và đưa vào Python 3. 8. Bạn sẽ thấy các ví dụ ngắn từ mỗi ví dụ này
PEP 586 giới thiệu loại.
# float_check.py
def double[number: float] -> float:
return 2 * number
double[3.14]
double["I'm not a float"]
0 hơi đặc biệt ở chỗ nó đại diện cho một hoặc một số giá trị cụ thể. Một trường hợp sử dụng của # float_check.py
def double[number: float] -> float:
return 2 * number
double[3.14]
double["I'm not a float"]
0 là có thể thêm chính xác các loại, khi các đối số chuỗi được sử dụng để mô tả hành vi cụ thể. Xem xét ví dụ sau$ python -m pip install mypy
6Chương trình sẽ vượt qua trình kiểm tra kiểu tĩnh, mặc dù
# float_check.py
def double[number: float] -> float:
return 2 * number
double[3.14]
double["I'm not a float"]
3 là hướng không hợp lệ. Trình kiểm tra loại chỉ kiểm tra xem # float_check.py
def double[number: float] -> float:
return 2 * number
double[3.14]
double["I'm not a float"]
3 có phải là một chuỗi không. Trong trường hợp này, sẽ chính xác hơn nếu nói hướng đó phải là chuỗi ký tự # float_check.py
def double[number: float] -> float:
return 2 * number
double[3.14]
double["I'm not a float"]
5 hoặc chuỗi ký tự # float_check.py
def double[number: float] -> float:
return 2 * number
double[3.14]
double["I'm not a float"]
6. Sử dụng # float_check.py
def double[number: float] -> float:
return 2 * number
double[3.14]
double["I'm not a float"]
0, bạn có thể làm chính xác điều đó$ python -m pip install mypy
2Bằng cách hiển thị các giá trị hướng được phép cho trình kiểm tra loại, giờ đây bạn có thể được cảnh báo về lỗi
$ python -m pip install mypy
3Cú pháp cơ bản là
# float_check.py
def double[number: float] -> float:
return 2 * number
double[3.14]
double["I'm not a float"]
8. Chẳng hạn, # float_check.py
def double[number: float] -> float:
return 2 * number
double[3.14]
double["I'm not a float"]
9 đại diện cho giá trị bằng chữ $ mypy float_check.py
float_check.py:8: error: Argument 1 to "double" has incompatible
type "str"; expected "float"
Found 1 error in 1 file [checked 1 source file]
0. Bạn có thể biểu thị một trong số các giá trị bằng chữ bằng cách sử dụng $ mypy float_check.py
float_check.py:8: error: Argument 1 to "double" has incompatible
type "str"; expected "float"
Found 1 error in 1 file [checked 1 source file]
1>>> double[3.14]
6.28
>>> double["I'm not a float"]
"I'm not a floatI'm not a float"
0Vì đây là trường hợp sử dụng khá phổ biến nên bạn có thể [và có lẽ nên] sử dụng ký hiệu đơn giản hơn là
$ mypy float_check.py
float_check.py:8: error: Argument 1 to "double" has incompatible
type "str"; expected "float"
Found 1 error in 1 file [checked 1 source file]
2 để thay thế. Bạn đã sử dụng cái sau khi thêm các loại vào $ mypy float_check.py
float_check.py:8: error: Argument 1 to "double" has incompatible
type "str"; expected "float"
Found 1 error in 1 file [checked 1 source file]
3Nếu bạn xem kỹ đầu ra từ Mypy ở trên, bạn có thể thấy rằng nó đã dịch ký hiệu đơn giản hơn sang ký hiệu Union trong nội bộ
Có những trường hợp loại giá trị trả về của hàm phụ thuộc vào đối số đầu vào. Một ví dụ là
$ mypy float_check.py
float_check.py:8: error: Argument 1 to "double" has incompatible
type "str"; expected "float"
Found 1 error in 1 file [checked 1 source file]
4, có thể trả về một chuỗi văn bản hoặc một mảng byte tùy thuộc vào giá trị của $ mypy float_check.py
float_check.py:8: error: Argument 1 to "double" has incompatible
type "str"; expected "float"
Found 1 error in 1 file [checked 1 source file]
5. Điều này có thể được xử lý thông quaVí dụ sau đây cho thấy bộ xương của một máy tính có thể trả về câu trả lời dưới dạng số thông thường [
$ mypy float_check.py
float_check.py:8: error: Argument 1 to "double" has incompatible
type "str"; expected "float"
Found 1 error in 1 file [checked 1 source file]
0] hoặc dưới dạng chữ số La Mã [$ mypy float_check.py
float_check.py:8: error: Argument 1 to "double" has incompatible
type "str"; expected "float"
Found 1 error in 1 file [checked 1 source file]
7]>>> double[3.14]
6.28
>>> double["I'm not a float"]
"I'm not a floatI'm not a float"
1Mã có gợi ý loại chính xác. kết quả của
$ mypy float_check.py
float_check.py:8: error: Argument 1 to "double" has incompatible
type "str"; expected "float"
Found 1 error in 1 file [checked 1 source file]
8 sẽ là $ mypy float_check.py
float_check.py:8: error: Argument 1 to "double" has incompatible
type "str"; expected "float"
Found 1 error in 1 file [checked 1 source file]
9 hoặc $ python -m pip install mypy
20. Tuy nhiên, thường thì mã này sẽ được gọi với một ký tự $ python -m pip install mypy
21 hoặc $ python -m pip install mypy
22 là giá trị của $ python -m pip install mypy
23, trong trường hợp đó, bạn muốn trình kiểm tra loại suy luận chính xác liệu $ mypy float_check.py
float_check.py:8: error: Argument 1 to "double" has incompatible
type "str"; expected "float"
Found 1 error in 1 file [checked 1 source file]
9 hay $ python -m pip install mypy
20 được trả về. Điều này có thể được thực hiện bằng cách sử dụng # float_check.py
def double[number: float] -> float:
return 2 * number
double[3.14]
double["I'm not a float"]
0 cùng với $ python -m pip install mypy
27>>> double[3.14]
6.28
>>> double["I'm not a float"]
"I'm not a floatI'm not a float"
2Các chữ ký ________ 127 được thêm vào sẽ giúp người kiểm tra loại của bạn suy ra ________ 99 hoặc ________ 120 tùy thuộc vào giá trị bằng chữ của
$ python -m pip install mypy
23. Lưu ý rằng các dấu chấm lửng [$ python -m pip install mypy
32] là một phần theo nghĩa đen của mã. Chúng đại diện cho thân hàm trong các chữ ký quá tảiĐể bổ sung cho
# float_check.py
def double[number: float] -> float:
return 2 * number
double[3.14]
double["I'm not a float"]
0, PEP 591 giới thiệu. Vòng loại này chỉ định rằng một biến hoặc thuộc tính không được gán lại, xác định lại hoặc ghi đè. Sau đây là một lỗi đánh máy>>> double[3.14]
6.28
>>> double["I'm not a float"]
"I'm not a floatI'm not a float"
3Mypy sẽ đánh dấu dòng
$ python -m pip install mypy
35 và lưu ý rằng bạn gán $ python -m pip install mypy
36 cho $ python -m pip install mypy
37. Điều này cung cấp cho bạn một cách để đảm bảo rằng các hằng số trong mã của bạn không bao giờ thay đổi giá trị của chúngNgoài ra, còn có một trình trang trí có thể được áp dụng cho các lớp và phương thức. Các lớp được trang trí bằng
$ python -m pip install mypy
38 không thể được phân lớp, trong khi các phương thức $ python -m pip install mypy
38 không thể bị ghi đè bởi các lớp con>>> double[3.14]
6.28
>>> double["I'm not a float"]
"I'm not a floatI'm not a float"
4Mypy sẽ gắn cờ ví dụ này với thông báo lỗi
$ python -m pip install mypy
61. Để tìm hiểu thêm về $ python -m pip install mypy
34 và $ python -m pip install mypy
38, hãy xem PEP 591PEP thứ ba cho phép gợi ý loại cụ thể hơn là PEP 589, giới thiệu. Điều này có thể được sử dụng để chỉ định các loại cho khóa và giá trị trong từ điển bằng cách sử dụng ký hiệu tương tự như đã nhập
Theo truyền thống, từ điển đã được chú thích bằng cách sử dụng. Vấn đề là điều này chỉ cho phép một loại cho các khóa và một loại cho các giá trị, thường dẫn đến các chú thích như
$ python -m pip install mypy
67. Ví dụ, hãy xem xét một từ điển đăng ký thông tin về các phiên bản Python>>> double[3.14]
6.28
>>> double["I'm not a float"]
"I'm not a floatI'm not a float"
5Giá trị tương ứng với
$ python -m pip install mypy
68 là một chuỗi, trong khi $ python -m pip install mypy
69 là một số nguyên. Điều này không thể được biểu diễn chính xác bằng cách sử dụng $ python -m pip install mypy
66. Với $ python -m pip install mypy
64 mới, bạn có thể làm như sau>>> double[3.14]
6.28
>>> double["I'm not a float"]
"I'm not a floatI'm not a float"
6Trình kiểm tra loại sau đó sẽ có thể suy ra rằng
$ python -m pip install mypy
22 có loại $ mypy float_check.py
float_check.py:8: error: Argument 1 to "double" has incompatible
type "str"; expected "float"
Found 1 error in 1 file [checked 1 source file]
9, trong khi $ python -m pip install mypy
24 là một $ python -m pip install mypy
20. Trong thời gian chạy, một $ python -m pip install mypy
64 là một $ python -m pip install mypy
27 thông thường và các gợi ý loại bị bỏ qua như bình thường>>>
>>> double[3.14]
6.28
>>> double["I'm not a float"]
"I'm not a floatI'm not a float"
7Mypy sẽ cho bạn biết nếu bất kỳ giá trị nào của bạn có loại sai hoặc nếu bạn sử dụng khóa chưa được khai báo. Xem PEP 589 để biết thêm ví dụ
Mypy đã hỗ trợ được một thời gian rồi. Tuy nhiên, việc nghiệm thu chính thức chỉ diễn ra vào tháng 5/2019
Các giao thức là một cách để chính thức hóa sự hỗ trợ của Python đối với việc gõ vịt
Khi tôi nhìn thấy một con chim đi như vịt, bơi như vịt và kêu quạc quạc như vịt, tôi gọi con chim đó là vịt. []
Kiểu gõ vịt cho phép bạn, ví dụ, đọc ________ 228 trên một đối tượng có thuộc tính ________ 228 mà không thực sự quan tâm đến loại đối tượng. Có vẻ như phản trực giác đối với hệ thống đánh máy để hỗ trợ điều này. Thông qua phân loại cấu trúc, vẫn có thể hiểu được cách gõ vịt
Ví dụ, bạn có thể xác định một giao thức có tên là
$ python -m pip install mypy
30 có thể xác định tất cả các đối tượng có thuộc tính $ python -m pip install mypy
28>>> double[3.14]
6.28
>>> double["I'm not a float"]
"I'm not a floatI'm not a float"
8Sau khi tạo giao thức
$ python -m pip install mypy
30 và xác định hàm $ python -m pip install mypy
33 nhận đối số là $ python -m pip install mypy
34, gợi ý loại xác định rằng $ python -m pip install mypy
34 tuân theo giao thức $ python -m pip install mypy
30. Chạy mã thông qua Mypy để xem những gì nó tìm thấy>>> double[3.14]
6.28
>>> double["I'm not a float"]
"I'm not a floatI'm not a float"
9Lớp
$ python -m pip install mypy
37 không có thuộc tính của $ python -m pip install mypy
28 và do đó không đáp ứng kiểm tra cho giao thức $ python -m pip install mypy
30. Thêm thuộc tính $ python -m pip install mypy
28 vào lớp, với chuỗi mặc định$ python -m pip install mypy
0Chạy lại
>>> double[3.14]
6.28
>>> double["I'm not a float"]
"I'm not a floatI'm not a float"
01 qua Mypy$ python -m pip install mypy
1Như bạn đã xác nhận,
$ python -m pip install mypy
33 lấy bất kỳ đối tượng nào, miễn là nó xác định thuộc tính $ python -m pip install mypy
28. Xem PEP 544 và tài liệu Mypy để biết thêm thông tin về các giao thức
Shehu Bello trên
Các tính năng rất thú vị. Tuy nhiên, với những tính năng này, python trông giống như một ngôn ngữ gõ tĩnh chẳng hạn như C
fofanovis trên
Lưu ý rằng dấu chấm lửng […] là một phần theo nghĩa đen của mã. Chúng đại diện cho thân hàm trong các chữ ký quá tải
Bạn có thể rất tử tế để giải thích về điều đó?
fofanovis trên
Theo truyền thống, từ điển đã được chú thích bằng Dict. Vấn đề là điều này chỉ cho phép một loại cho các khóa và một loại cho các giá trị, thường dẫn đến các chú thích như Dict[str, Any]
Liên kết bạn cung cấp dẫn đến tài liệu trong đó Dict được sử dụng trong khai báo hàm và Dict khai báo cả hai loại và chúng khác nhau
$ python -m pip install mypy
2fofanovis trên
Oh, tôi đoán tôi đã nhận nó. TypedDict là trường hợp khi chúng ta biết trước tất cả các khóa. Không có cách nào để thêm bao nhiêu cặp khóa-giá trị như chúng tôi muốn vào một TypedDict. Ngược lại, chúng ta có thể làm điều đó với một Dict thông thường. Trên thực tế, những loại này rất khác nhau, cuối cùng. Thậm chí không nói về sự khác biệt đánh máy
Geir Arne Hjelle Nhóm RP trên
Đúng. Tôi đoán bạn có thể phân loại hầu hết các cách sử dụng từ điển thành một trong hai trường hợp sử dụng
Từ điển được sử dụng như một loại danh sách được lập chỉ mục, nơi bạn thường không cần có ý tưởng rõ ràng trước về số lượng mục bạn sẽ có. Ví dụ
25# float_check.py def double[number: float] -> float: return 2 * number double[3.14] double["I'm not a float"]
Đối với những trường hợp này, một cái gì đó như
26 là một mô tả tốt về các loại được sử dụng trong từ điển# float_check.py def double[number: float] -> float: return 2 * number double[3.14] double["I'm not a float"]
Từ điển được sử dụng tương tự như hàng cơ sở dữ liệu hoặc bộ được đặt tên. Trong trường hợp này, cấu trúc của từ điển thường chặt chẽ hơn. Ví dụ
27# float_check.py def double[number: float] -> float: return 2 * number double[3.14] double["I'm not a float"]
Đối với những trường hợp này, các giá trị thường thuộc các loại khác nhau, do đó, loại "đơn giản" duy nhất có thể được sử dụng thuận tiện là
67. Tuy nhiên,$ python -m pip install mypy
74 không thực sự cung cấp bất kỳ thông tin hữu ích nào. Thay vào đó, có thể sử dụng$ python -m pip install mypy
64 để nắm bắt chính xác loại từ điển này$ python -m pip install mypy
Tôi đoán rằng hầu hết các cách sử dụng thực tế của loại từ điển thứ hai này, có các từ điển này được lồng bên trong một cấu trúc dữ liệu khác, như danh sách hoặc từ điển trường hợp-1 [ví dụ:
31]# float_check.py def double[number: float] -> float: return 2 * number double[3.14] double["I'm not a float"]
Chris Bailey Nhóm RP trên
Xin chào @fofanovis, Về dấu chấm lửng
$ python -m pip install mypy
32 trong hai chữ ký ________ 127 ________ 834 Tình trạng quá tải không phải là xác định lại hàm, mà là xác định lại các loại dự kiến sẽ được trả về. Và cú pháp cho phép bạn không bao gồm toàn bộ định nghĩa hàm trong câu lệnh quá tải mà sử dụng dấu chấm lửng làm trình giữ chỗ cho phần còn lại của hàm. Cuộc thảo luận này về các vấn đề về python/gõ 'sơ khai' 109 bao gồm một số vấn đề. Tôi nghĩ Geir Arne sẽ biết nhiều hơn một chút, vì anh ấy là tác giả của bài báo gốcvang thu vào
Tôi thực sự thích tùy chọn theo nghĩa đen đó. Một trong những điều khiến tôi khó chịu nhất khi học Python là số lượng chuỗi mã hóa cứng được sử dụng trong mã. Trong C#, tôi luôn nhấn mạnh rằng đây là điều tồi tệ nhất có thể tưởng tượng được mà bạn có thể làm vì rất dễ mắc lỗi chính tả và gây ra lỗi.
Tôi thường giải quyết vấn đề này trong C# bằng cách sử dụng enums [như color. Màu đỏ. MÀU XANH, v.v. , thay vì “đỏ”, “xanh”]. Đây có phải là một thay thế chấp nhận được? . NGANG và hướng. VERTICAL là hai thành viên của hướng enum?
Giao thức này nghe cũng rất hay và tôi đã đặc biệt tự hỏi liệu có thứ gì đó giống như vậy tồn tại hay không nên tôi rất vui khi được giải thích điều đó
Mặc dù tôi vẫn không chắc liệu việc sử dụng tất cả kiểu gõ này có chấp nhận được không? . Mọi người có thất vọng với mã của tôi không nếu mọi chức năng đều bao gồm các gợi ý về loại?