Sự khác nhau giữa định nghĩa kiểu gõ.Dict và dict?


102

Tôi đang thực hành sử dụng gợi ý kiểu trong Python 3.5. Một trong những đồng nghiệp của tôi sử dụng typing.Dict:

import typing


def change_bandwidths(new_bandwidths: typing.Dict,
                      user_id: int,
                      user_name: str) -> bool:
    print(new_bandwidths, user_id, user_name)
    return False


def my_change_bandwidths(new_bandwidths: dict,
                         user_id: int,
                         user_name: str) ->bool:
    print(new_bandwidths, user_id, user_name)
    return True


def main():
    my_id, my_name = 23, "Tiras"
    simple_dict = {"Hello": "Moon"}
    change_bandwidths(simple_dict, my_id, my_name)
    new_dict = {"new": "energy source"}
    my_change_bandwidths(new_dict, my_id, my_name)

if __name__ == "__main__":
    main()

Cả hai đều hoạt động tốt, dường như không có sự khác biệt.

Tôi đã đọc typingtài liệu mô-đun .

Tôi nên sử dụng cái nào giữa typing.Dicthay dictcái nào trong chương trình?


11
Lưu ý rằng Python không thực sự thực thi các gợi ý kiểu. Chúng chỉ là gợi ý , chúng không được sử dụng trong thời gian chạy, hoặc thậm chí thời gian biên dịch, để thực thi các kiểu. Python có thể được gõ mạnh (ngược lại với gõ yếu), nó cũng được gõ động (ngược lại với gõ nghiêm ngặt). Xem Python có được gõ mạnh không? . Tuy nhiên, các công cụ bên ngoài như mypy có thể sử dụng những gợi ý này để giúp bạn viết mã tốt hơn, trong một quá trình được gọi là phân tích tĩnh.
Martijn Pieters

1
@MartijnPieters Tôi đã từng thích sử dụng gợi ý kiểu trong mã của mình cùng với MyPy và giả vờ rằng tôi có thể sử dụng Python với sự an toàn về kiểu. Thật không may, nó đã khiến tôi A) mã không hoạt động trên <3,4 và B) mọi người cười nhạo tôi bởi vì rõ ràng, gợi ý kiểu là một trò cười. Nó thực sự khá đáng tiếc.
con mèo

3
@cat: Loại gián tiếp được giới thiệu với Python bởi một nhân viên Facebook, bởi vì chúng tôi đã có rất lớn thành công với việc thêm tính năng tương tự để PHP (xem Hack ). Bất cứ ai cười cũng chưa bao giờ xây dựng một dự án lớn với nhiều hơn một số kỹ sư.
Martijn Pieters

3
@MartijnPieters Không, def a(b: int) -> bool:là lỗi cú pháp trong Python 2.7 và tôi nghĩ đó cũng là lỗi cú pháp trong các phiên bản cũ hơn của Python 3.
con mèo

1
@cat: bạn đang nói về chú thích hàm ở đây, cú pháp đã được thêm vào Python 3.0. Vì vậy, phiên bản duy nhất có lỗi cú pháp là 2.7, đó là lý do tại sao mypy hỗ trợ đưa thông tin đó vào bình luận.
Martijn Pieters

Câu trả lời:


141

Không có sự khác biệt thực sự giữa sử dụng đơn giản typing.Dictdict, không.

Tuy nhiên, typing.Dictlà một loại Generic cho phép bạn chỉ định các loại khóa và giá trị quá , làm cho nó linh hoạt hơn:

def change_bandwidths(new_bandwidths: typing.Dict[str, str],
                      user_id: int,
                      user_name: str) -> bool:

Như vậy, có thể là tại một thời điểm nào đó trong vòng đời dự án của bạn, bạn muốn xác định đối số từ điển chính xác hơn một chút, lúc đó việc mở rộng typing.Dictthành typing.Dict[key_type, value_type]là một thay đổi 'nhỏ hơn' so với thay thế dict.

Bạn có thể làm cho điều này thậm chí còn chung chung hơn bằng cách sử dụng Mappinghoặc MutableMappingcác loại ở đây; vì hàm của bạn không cần phải thay đổi ánh xạ, tôi sẽ gắn bó với Mapping. A dictlà một ánh xạ, nhưng bạn có thể tạo các đối tượng khác cũng đáp ứng giao diện ánh xạ và chức năng của bạn có thể vẫn hoạt động với những đối tượng đó:

def change_bandwidths(new_bandwidths: typing.Mapping[str, str],
                      user_id: int,
                      user_name: str) -> bool:

Bây giờ bạn đang nói rõ ràng những người dùng khác của chức năng này là mã của bạn sẽ không thực sự làm thay đổi các new_bandwidthsbản đồ thông qua vào.

Việc triển khai thực tế của bạn chỉ là mong đợi một đối tượng có thể in được. Đó có thể là một triển khai thử nghiệm, nhưng vì nó là mã của bạn sẽ tiếp tục hoạt động nếu bạn đã sử dụng new_bandwidths: typing.Any, vì bất kỳ đối tượng nào trong Python đều có thể in được.


2
Các ví dụ bổ sung hữu ích sẽ là khi các giá trị từ điển có thể là các kiểu khác nhau {"name": "bob", "age" : 51}, ví dụ , đó sẽ là một cái gì đó như thế typing.Mapping[Union[str, int]nào? Điều gì về một từ điển lồng nhau {"person": {"name":"bob", "age": 51}sẽ như thế typing.Mapping[str, typing.Mapping[Union[str, int]]nào? Việc sử dụng Unionnhư vậy làm phiền tôi vì nó không phải là một lược đồ nghiêm ngặt vì không có thứ tự. Có lẽ đó là OK, hoặc có một giải pháp thay thế?
Davos

1
Đừng bận tâm về Unioncâu hỏi mà tôi thấy đó vẫn là một cuộc thảo luận mở github.com/python/typing/issues/28
Davos

1
Điều này có vẻ rất thú vị, hữu ích và có liên quan python.org/dev/peps/pep-0589
Greg Hilston

@GregHilston: đó thực sự là về cách hạn chế những khóa mà từ điển có thể chứa và chỉ định loại mà mỗi giá trị được liên kết nên có.
Martijn Pieters

1
@GregHilston: à, đúng rồi.
Martijn Pieters

26

typing.Dictlà phiên bản chung của dict:

class typing.Dict(dict, MutableMapping[KT, VT])

Một phiên bản chung của dict. Cách sử dụng của loại này như sau:

def get_position_in_index(word_list: Dict[str, int], word: str) -> int:
     return word_list[word]

Tại đây bạn có thể chỉ định loại khóa và giá trị trong dict: Dict[str, int]

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.