Python gõ dict với nhiều loại

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ổi

Gợ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
2

Bây giờ hãy chạy lại Mypy trên mã này

$ python -m pip install mypy
3

Theo 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
6

Chươ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
2

Bằ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
3

Cú 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"
0

Vì đâ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]
3

Nế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 qua

Ví 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"
1

Mã 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"
2

Cá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"
3

Mypy 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úng

Ngoà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"
4

Mypy 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 591

PEP 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"
5

Giá 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"
6

Trì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"
7

Mypy 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"
8

Sau 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"
9

Lớ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
0

Chạ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
1

Như 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
2

fofanovis 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

  1. 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ụ

    # float_check.py
    
    def double[number: float] -> float:
        return 2 * number
    
    double[3.14]
    
    double["I'm not a float"]
    
    25

    Đối với những trường hợp này, một cái gì đó như

    # float_check.py
    
    def double[number: float] -> float:
        return 2 * number
    
    double[3.14]
    
    double["I'm not a float"]
    
    26 là một mô tả tốt về các loại được sử dụng trong từ điển

  2. 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ụ

    # float_check.py
    
    def double[number: float] -> float:
        return 2 * number
    
    double[3.14]
    
    double["I'm not a float"]
    
    27

    Đố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à

    $ python -m pip install mypy
    
    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

    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ụ:

    # float_check.py
    
    def double[number: float] -> float:
        return 2 * number
    
    double[3.14]
    
    double["I'm not a float"]
    
    31]

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ốc

vang 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?

Từ điển có thể có nhiều loại dữ liệu Python không?

Ví dụ: bạn có thể sử dụng số nguyên, số float, chuỗi hoặc Boolean làm khóa từ điển. Tuy nhiên, cả danh sách và từ điển khác đều không thể dùng làm khóa từ điển vì danh sách và từ điển có thể thay đổi . Mặt khác, các giá trị có thể là bất kỳ loại nào và có thể được sử dụng nhiều lần.

Từ điển Python có thể chứa các loại khác nhau không?

Giống như danh sách, giá trị của từ điển có thể chứa dữ liệu không đồng nhất i. e. , số nguyên, số float, chuỗi, NaN, Booleans, danh sách, mảng và thậm chí cả từ điển lồng nhau . Bài viết này sẽ giúp bạn hiểu rõ và giúp bạn làm việc thành thạo với từ điển Python.

Từ điển có thể có nhiều kiểu dữ liệu không?

Một người chỉ có thể đưa một loại đối tượng vào từ điển . Nếu một người muốn đưa nhiều loại dữ liệu vào cùng một từ điển, e. g. đối với thông tin cấu hình hoặc các kho lưu trữ dữ liệu phổ biến khác, phải sử dụng siêu lớp của tất cả các loại dữ liệu được lưu giữ có thể để xác định từ điển.

Các giá trị từ điển Python có thể có các loại dữ liệu khác nhau không?

Các giá trị của từ điển có thể thuộc bất kỳ loại nào , nhưng các khóa phải thuộc loại dữ liệu bất biến, chẳng hạn như chuỗi, số hoặc bộ.

Chủ Đề