Tôi sẽ khuyên bạn nên sử dụng phiên bản đầu tiên, nơi bạn gán các loại cho các tham số của phương thức
path = None # type: Optional[str] # Path to module source4, trong hầu hết các trường hợp.
Phương pháp cụ thể đó có số lượng dự phòng ít nhất trong khi vẫn cho phép trình kiểm tra loại xác minh rằng bạn đang gọi phương thức
path = None # type: Optional[str] # Path to module source4 đó một cách chính xác ở nơi khác trong mã của bạn.
Tôi sẽ khuyên bạn nên sử dụng phiên bản thứ hai hoặc thứ ba, trong đó bạn chú thích rõ ràng các trường của mình [bên trong hoặc bên ngoài
path = None # type: Optional[str] # Path to module source4] khi phương thức
path = None # type: Optional[str] # Path to module source4 của bạn đã phát triển đủ phức tạp đến mức áp dụng một hoặc nhiều điều sau đây:
- Nó không còn đơn giản hơn chính xác các trường của bạn sẽ bắt đầu
- Không còn ánh xạ một-một giữa các tham số và trường của bạn
- Bạn có logic khởi tạo phức tạp che khuất cách các trường của bạn được gán.
Tuy nhiên, không rõ tôi là phiên bản thứ hai hay thứ ba được ưa thích - cá nhân tôi thích phiên bản thứ ba vì nó sạch hơn về mặt khái niệm và dường như không kết hợp khái niệm về thể hiện so với các thuộc tính của lớp, nhưng tôi không thể phủ nhận Phiên bản thứ hai trông sạch hơn.
Tôi đã hỏi về nó trên kênh Gitter 'gõ' và nhận được phản hồi sau từ Guido [người, trên cơ hội mà bạn không biết, đã tạo Python và hiện đang làm việc trên MyPy và gõ các thứ liên quan]:
Dường như có những ý kiến mạnh mẽ bằng cách nào đó. Tôi thực sự thích đặt các chú thích thuộc tính vào cơ thể lớp hơn là rắc chúng trong suốt
path = None # type: Optional[str] # Path to module source4 và các phương pháp khác. Tôi cũng nghĩ rằng với PEP 526, đây sẽ là tương lai [cũng với những thứ như tuyên bố được đặt tên dựa trên lớp và có thể //github.com/ericvsmith/dataclasses].
[liên kết đến báo giá]
Vì vậy, có vẻ như phiên bản thứ hai được khuyến nghị trong phiên bản thứ ba và việc xác định các lớp theo cách đó sẽ được tích hợp sâu hơn vào chính ngôn ngữ Python tại một số điểm trong tương lai!
EDIT: PEP 557, các lớp dữ liệu gần đây đã được chấp nhận và dường như được theo dõi [?] Để được bao gồm với Python 3.7. PEP 557, data classes was recently accepted and appears to be on-track [?] to be included with Python 3.7.
- Trạng thái
- Thông báo cho người đánh giá
- trừu tượng
- Cơ sở lý luận
- Non-goals
- Sự chỉ rõ
- Chú thích biến toàn cầu và địa phương
- Chú thích biến lớp và phiên bản
- Chú thích biểu thức
- Nơi chú thích aren cho phép
- Chú thích biến trong các tệp sơ khai
- Kiểu mã hóa ưa thích cho các chú thích thay đổi
- Thay đổi đối với thư viện và tài liệu tiêu chuẩn
- Hiệu ứng thời gian chạy của các chú thích loại
- Các công dụng khác của chú thích
- Các đề xuất bị từ chối/hoãn lại
- Khả năng tương thích ngược
- Thực hiện
- Bản quyền
Trạng thái
Thông báo cho người đánh giá
Thông báo cho người đánh giá
trừu tượng
Cơ sở lý luận
Sự chỉ rõ
trừu tượng
Cơ sở lý luận
# 'primes' is a list of integers primes = [] # type: List[int] # 'captain' is a string [Note: initial value is a problem] captain = ... # type: str class Starship: # 'stats' is a class variable stats = {} # type: Dict[str, int]
Sự chỉ rõ
primes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: ClassVar[Dict[str, int]] = {}
Chú thích biến toàn cầu và địa phương
Cơ sở lý luận
Sự chỉ rõ
- Chú thích biến toàn cầu và địa phương
- Chú thích biến lớp và phiên bản
- Chú thích biểu thức
if some_value: my_var = function[] # type: Logger else: my_var = another_function[] # Why isn't there a type here?
- Vì các nhận xét loại thực sự là một phần của ngôn ngữ, nếu một tập lệnh Python muốn phân tích chúng, nó yêu cầu một trình phân tích cú pháp tùy chỉnh thay vì chỉ sử dụng
my_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.
1. - Loại bình luận được sử dụng rất nhiều trong đánh máy. Di chuyển được đánh máy để sử dụng cú pháp chú thích thay đổi thay vì các bình luận loại sẽ cải thiện khả năng đọc của các cuống.
- Trong các tình huống mà các bình luận và nhận xét loại bình thường được sử dụng cùng nhau, rất khó để phân biệt chúng:
path = None # type: Optional[str] # Path to module source
- Nó không thể truy xuất các chú thích trong thời gian chạy bên ngoài cố gắng tìm mã nguồn mô -đun và phân tích nó trong thời gian chạy, không phù hợp, để nói rằng ít nhất.
Phần lớn các vấn đề này có thể được giảm bớt bằng cách biến cú pháp thành một phần cốt lõi của ngôn ngữ. Hơn nữa, có một cú pháp chú thích chuyên dụng cho các biến lớp và trường hợp [ngoài các chú thích phương pháp] sẽ mở đường cho việc gõ vịt tĩnh như một bổ sung để gõ danh nghĩa được xác định bởi PEP 484.
Non-goals
Mặc dù đề xuất đi kèm với phần mở rộng của chức năng thư viện tiêu chuẩn
my_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.2 để truy xuất các chú thích thời gian chạy, các chú thích biến không được thiết kế để kiểm tra loại thời gian chạy. Các gói của bên thứ ba sẽ phải được phát triển để thực hiện chức năng đó.
Cũng cần nhấn mạnh rằng Python sẽ vẫn là một ngôn ngữ được đánh máy động và các tác giả không muốn làm cho các gợi ý loại bắt buộc, ngay cả theo quy ước. Loại chú thích không nên bị nhầm lẫn với các khai báo biến trong các ngôn ngữ được đánh máy tĩnh. Mục tiêu của cú pháp chú thích là cung cấp một cách dễ dàng để chỉ định siêu dữ liệu loại có cấu trúc cho các công cụ của bên thứ ba.Python will remain a dynamically typed language, and the authors have no desire to ever make type hints mandatory, even by convention. Type annotations should not be confused with variable declarations in statically typed languages. The goal of annotation syntax is to provide an easy way to specify structured type metadata for third party tools.
PEP này không yêu cầu trình kiểm tra loại để thay đổi quy tắc kiểm tra loại của họ. Nó chỉ cung cấp một cú pháp dễ đọc hơn để thay thế các bình luận loại.
Sự chỉ rõ
Loại chú thích có thể được thêm vào một câu lệnh gán hoặc vào một biểu thức duy nhất cho biết loại mục tiêu chú thích mong muốn cho trình kiểm tra loại bên thứ ba:
my_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.
Cú pháp này không giới thiệu bất kỳ ngữ nghĩa mới nào ngoài PEP 484, do đó ba câu sau là tương đương:
var = value # type: annotation var: annotation; var = value var: annotation = value
Dưới đây chúng tôi chỉ định cú pháp của các chú thích loại trong các bối cảnh khác nhau và hiệu ứng thời gian chạy của chúng.
Chúng tôi cũng đề xuất làm thế nào trình kiểm tra loại có thể giải thích các chú thích, nhưng việc tuân thủ các đề xuất này là không bắt buộc. [Điều này phù hợp với thái độ tuân thủ trong PEP 484.]
Chú thích biến toàn cầu và địa phương
Các loại người dân địa phương và toàn cầu có thể được chú thích như sau:
some_number: int # variable without initial value some_list: List[int] = [] # variable with initial value
Có thể bỏ qua giá trị ban đầu cho phép gõ các biến dễ dàng hơn được gán trong các nhánh có điều kiện:
sane_world: bool if 2+2 == 4: sane_world = True else: sane_world = False
Lưu ý rằng, mặc dù cú pháp không cho phép đóng gói tple, nhưng nó không cho phép người ta chú thích các loại biến khi sử dụng việc giải nén tuple:
# Tuple packing with variable annotation syntax t: Tuple[int, ...] = [1, 2, 3] # or t: Tuple[int, ...] = 1, 2, 3 # This only works in Python 3.8+ # Tuple unpacking with variable annotation syntax header: str kind: int body: Optional[List[str]] header, kind, body = message
Bỏ qua giá trị ban đầu để lại biến không chính xác:
a: int print[a] # raises NameError
Tuy nhiên, việc chú thích một biến cục bộ sẽ khiến thông dịch viên luôn biến nó thành một địa phương:
primes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: ClassVar[Dict[str, int]] = {}0
Như thể mã là:
primes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: ClassVar[Dict[str, int]] = {}1
Chú thích loại trùng lặp sẽ bị bỏ qua. Tuy nhiên, trình kiểm tra loại tĩnh có thể đưa ra cảnh báo cho các chú thích của cùng một biến theo một loại khác:
primes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: ClassVar[Dict[str, int]] = {}2
Chú thích biến lớp và phiên bản
Các chú thích loại cũng có thể được sử dụng để chú thích các biến lớp và thể hiện trong các cơ quan và phương pháp lớp. Cụ thể, ký hiệu không có giá trị
my_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.3 cho phép người ta chú thích các biến thể hiện nên được khởi tạo trong
my_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.4 hoặc
my_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.5. Cú pháp được đề xuất như sau:
primes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: ClassVar[Dict[str, int]] = {}3
Ở đây
my_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.6 là một lớp đặc biệt được xác định bởi mô -đun gõ cho biết trình kiểm tra loại tĩnh rằng biến này không nên được đặt trên các trường hợp.
Lưu ý rằng tham số
my_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.6 không thể bao gồm bất kỳ biến loại nào, bất kể mức độ lồng nhau:
my_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.8 và
my_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.9 đều không hợp lệ nếu
var = value # type: annotation var: annotation; var = value var: annotation = value0 là biến loại.
Điều này có thể được minh họa với một ví dụ chi tiết hơn. Trong lớp học này:
primes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: ClassVar[Dict[str, int]] = {}4
var = value # type: annotation var: annotation; var = value var: annotation = value1 được dự định là một biến lớp [theo dõi nhiều số liệu thống kê trên mỗi trò chơi khác nhau], trong khi
var = value # type: annotation var: annotation; var = value var: annotation = value2 là một biến thể hiện với giá trị mặc định được đặt trong lớp. Sự khác biệt này có thể không được nhìn thấy bởi một trình kiểm tra loại: cả hai đều được khởi tạo trong lớp, nhưng
var = value # type: annotation var: annotation; var = value var: annotation = value2 chỉ đóng vai trò là giá trị mặc định thuận tiện cho biến thể hiện, trong khi
var = value # type: annotation var: annotation; var = value var: annotation = value1 thực sự là một biến lớp - nó được dự định sẽ được chia sẻ bởi tất cả các trường hợp.
Vì cả hai biến xảy ra được khởi tạo ở cấp độ lớp, nên rất hữu ích khi phân biệt chúng bằng cách đánh dấu các biến lớp là chú thích với các loại được bọc trong
var = value # type: annotation var: annotation; var = value var: annotation = value5. Theo cách này, một trình kiểm tra loại có thể gắn cờ các bài tập tình cờ vào các thuộc tính có cùng tên trên các trường hợp.
Ví dụ, chú thích lớp đã thảo luận:
primes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: ClassVar[Dict[str, int]] = {}5
Như một vấn đề thuận tiện [và quy ước], các biến thể hiện có thể được chú thích trong
my_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.4 hoặc các phương thức khác, thay vì trong lớp:
primes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: ClassVar[Dict[str, int]] = {}6
Chú thích biểu thức
Mục tiêu của chú thích có thể là bất kỳ mục tiêu gán duy nhất hợp lệ nào, ít nhất là về mặt cú pháp [tùy thuộc vào kiểu kiểm tra loại phải làm gì với điều này]:
primes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: ClassVar[Dict[str, int]] = {}7
Lưu ý rằng ngay cả một tên ngoặc cũng được coi là một biểu thức, không phải là một tên đơn giản:
primes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: ClassVar[Dict[str, int]] = {}8
Nơi chú thích aren cho phép
Việc cố gắng chú thích các biến theo
var = value # type: annotation var: annotation; var = value var: annotation = value7 hoặc
var = value # type: annotation var: annotation; var = value var: annotation = value8 là bất hợp pháp trong cùng một phạm vi chức năng:
primes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: ClassVar[Dict[str, int]] = {}9
Lý do là các biến riêng của
var = value # type: annotation var: annotation; var = value var: annotation = value7 và
var = value # type: annotation var: annotation; var = value var: annotation = value8 don don; Do đó, các chú thích loại thuộc về phạm vi sở hữu biến.
Chỉ được phép cho phép các mục tiêu gán đơn và các giá trị bên tay phải duy nhất được cho phép. Ngoài ra, người ta không thể chú thích các biến được sử dụng trong câu lệnh
some_number: int # variable without initial value some_list: List[int] = [] # variable with initial value1 hoặc
some_number: int # variable without initial value some_list: List[int] = [] # variable with initial value2; Chúng có thể được chú thích trước thời hạn, theo cách tương tự như giải nén:
if some_value: my_var = function[] # type: Logger else: my_var = another_function[] # Why isn't there a type here?0
Chú thích biến trong các tệp sơ khai
Vì các chú thích thay đổi dễ đọc hơn các bình luận loại, chúng được ưa thích trong các tệp sơ khai cho tất cả các phiên bản của Python, bao gồm Python 2.7. Lưu ý rằng các tệp sơ khai không được thực thi bởi các phiên dịch viên Python và do đó sử dụng các chú thích thay đổi sẽ không dẫn đến lỗi. Kiểu kiểm tra loại nên hỗ trợ các chú thích thay đổi trong các cuống cho tất cả các phiên bản của Python. Ví dụ:
if some_value: my_var = function[] # type: Logger else: my_var = another_function[] # Why isn't there a type here?1
Kiểu mã hóa ưa thích cho các chú thích thay đổi
Chú thích cho các biến cấp mô -đun, các biến lớp và thể hiện và các biến cục bộ phải có một không gian duy nhất sau khi đại tràng tương ứng. Không nên có không gian trước đại tràng. Nếu một nhiệm vụ có phía bên tay phải, thì dấu hiệu bình đẳng sẽ có chính xác một khoảng trống ở cả hai bên. Ví dụ:
- Đúng:
if some_value: my_var = function[] # type: Logger else: my_var = another_function[] # Why isn't there a type here?
2 - No:
if some_value: my_var = function[] # type: Logger else: my_var = another_function[] # Why isn't there a type here?
3
Thay đổi đối với thư viện và tài liệu tiêu chuẩn
- Một loại đồng biến mới
some_number: int # variable without initial value some_list: List[int] = [] # variable with initial value
3 được thêm vào mô -đunsome_number: int # variable without initial value some_list: List[int] = [] # variable with initial value
4. Nó chỉ chấp nhận một đối số duy nhất phải là một loại hợp lệ và được sử dụng để chú thích các biến lớp không nên được đặt trên các phiên bản lớp. Hạn chế này được đảm bảo bởi các trình kiểm tra tĩnh, nhưng không phải là thời gian chạy. Xem phần Classvar để biết các ví dụ và giải thích về việc sử dụngmy_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.
6 và xem phần bị từ chối để biết thêm thông tin về lý do đằng saumy_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.
6. - Chức năng
some_number: int # variable without initial value some_list: List[int] = [] # variable with initial value
7 Trong mô -đunsome_number: int # variable without initial value some_list: List[int] = [] # variable with initial value
4 sẽ được mở rộng, để người ta có thể truy xuất các chú thích loại trong thời gian chạy từ các mô -đun và các lớp cũng như các chức năng. Các chú thích được trả về dưới dạng ánh xạ từ điển từ biến hoặc đối số cho các gợi ý loại của chúng với các tài liệu tham khảo phía trước được đánh giá. Đối với các lớp, nó trả về một ánh xạ [có lẽsome_number: int # variable without initial value some_list: List[int] = [] # variable with initial value
9] được xây dựng từ các chú thích theo thứ tự phân giải phương thức. - Các hướng dẫn được đề xuất để sử dụng các chú thích sẽ được thêm vào tài liệu, chứa một bản tóm tắt sư phạm về các thông số kỹ thuật được mô tả trong PEP này và trong PEP 484. Ngoài ra, một tập lệnh trợ giúp để dịch các nhận xét loại thành các chú thích loại sẽ được xuất bản tách biệt với thư viện tiêu chuẩn.
Hiệu ứng thời gian chạy của các chú thích loại
Chú thích một biến cục bộ sẽ khiến thông dịch viên coi nó như một địa phương, ngay cả khi nó không bao giờ được chỉ định. Chú thích cho các biến cục bộ sẽ không được đánh giá:
if some_value: my_var = function[] # type: Logger else: my_var = another_function[] # Why isn't there a type here?4
Tuy nhiên, nếu nó ở cấp độ mô -đun hoặc lớp, thì loại sẽ được đánh giá:
if some_value: my_var = function[] # type: Logger else: my_var = another_function[] # Why isn't there a type here?5
Ngoài ra, ở cấp độ mô -đun hoặc lớp, nếu mục được chú thích là một cái tên đơn giản, thì nó và chú thích sẽ được lưu trữ trong thuộc tính
sane_world: bool if 2+2 == 4: sane_world = True else: sane_world = False0 của mô -đun hoặc lớp [bị xáo trộn nếu riêng tư] như một bản đồ được đặt hàng từ tên để đánh giá Chú thích. Đây là một ví dụ:
if some_value: my_var = function[] # type: Logger else: my_var = another_function[] # Why isn't there a type here?6
sane_world: bool if 2+2 == 4: sane_world = True else: sane_world = False0 có thể ghi, vì vậy điều này được cho phép:
if some_value: my_var = function[] # type: Logger else: my_var = another_function[] # Why isn't there a type here?7
Nhưng việc cố gắng cập nhật
sane_world: bool if 2+2 == 4: sane_world = True else: sane_world = False0 lên một cái gì đó khác ngoài ánh xạ được đặt hàng có thể dẫn đến một kiểu mẫu:
if some_value: my_var = function[] # type: Logger else: my_var = another_function[] # Why isn't there a type here?8
.
Cách khuyến nghị để nhận được các chú thích trong thời gian chạy là sử dụng hàm
my_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.2; Như với tất cả các thuộc tính Dunder, bất kỳ việc sử dụng
sane_world: bool if 2+2 == 4: sane_world = True else: sane_world = False0 không bị phá vỡ mà không bị cảnh báo:
if some_value: my_var = function[] # type: Logger else: my_var = another_function[] # Why isn't there a type here?9
Lưu ý rằng nếu các chú thích không được tìm thấy thống kê, thì từ điển
sane_world: bool if 2+2 == 4: sane_world = True else: sane_world = False0 hoàn toàn không được tạo ra. Ngoài ra, giá trị của việc có các chú thích có sẵn tại địa phương không bù đắp chi phí phải tạo và điền từ điển chú thích trên mỗi cuộc gọi chức năng. Do đó, các chú thích ở cấp độ chức năng không được đánh giá và không được lưu trữ.
Các công dụng khác của chú thích
Trong khi Python với PEP này sẽ không phản đối:
path = None # type: Optional[str] # Path to module source0
Vì nó sẽ không quan tâm đến việc chú thích loại ngoài phạm vi đánh giá mà không cần nâng cao, một trình kiểm tra loại gặp phải nó sẽ gắn cờ nó, trừ khi bị vô hiệu hóa với
sane_world: bool if 2+2 == 4: sane_world = True else: sane_world = False8 hoặc
sane_world: bool if 2+2 == 4: sane_world = True else: sane_world = False9.
Tuy nhiên, vì Python đã giành được sự chăm sóc của loại hình này là gì, nếu đoạn trích ở trên ở cấp độ toàn cầu hoặc trong một lớp,
sane_world: bool if 2+2 == 4: sane_world = True else: sane_world = False0 sẽ bao gồm
# Tuple packing with variable annotation syntax t: Tuple[int, ...] = [1, 2, 3] # or t: Tuple[int, ...] = 1, 2, 3 # This only works in Python 3.8+ # Tuple unpacking with variable annotation syntax header: str kind: int body: Optional[List[str]] header, kind, body = message1.
Những chú thích được lưu trữ này có thể được sử dụng cho các mục đích khác, nhưng với PEP này, chúng tôi đề xuất rõ ràng gợi ý loại là việc sử dụng các chú thích ưa thích.
Các đề xuất bị từ chối/hoãn lại
- Chúng ta có nên giới thiệu các chú thích thay đổi ở tất cả không? Các chú thích thay đổi đã có từ gần hai năm dưới dạng nhận xét loại, bị PEP 484. Chúng được sử dụng rộng rãi bởi các trình kiểm tra loại bên thứ ba [MyPy, PyType, Pycharm, v.v.] và bởi các dự án sử dụng trình kiểm tra loại. Tuy nhiên, cú pháp nhận xét có nhiều nhược điểm được liệt kê trong Rationale. PEP này không phải là về sự cần thiết của các chú thích loại, mà là về những gì nên là cú pháp cho các chú thích như vậy. Variable annotations have already been around for almost two years in the form of type comments, sanctioned by PEP 484. They are extensively used by third party type checkers [mypy, pytype, PyCharm, etc.] and by projects using the type checkers. However, the comment syntax has many downsides listed in Rationale. This PEP is not about the need for type annotations, it is about what should be the syntax for such annotations.
- Giới thiệu một từ khóa mới: Việc lựa chọn từ khóa tốt là khó, ví dụ: Nó có thể là
# Tuple packing with variable annotation syntax t: Tuple[int, ...] = [1, 2, 3] # or t: Tuple[int, ...] = 1, 2, 3 # This only works in Python 3.8+ # Tuple unpacking with variable annotation syntax header: str kind: int body: Optional[List[str]] header, kind, body = message
2 bởi vì đó là một tên biến quá phổ biến và nó có thể là# Tuple packing with variable annotation syntax t: Tuple[int, ...] = [1, 2, 3] # or t: Tuple[int, ...] = 1, 2, 3 # This only works in Python 3.8+ # Tuple unpacking with variable annotation syntax header: str kind: int body: Optional[List[str]] header, kind, body = message
3 nếu chúng ta muốn sử dụng nó cho các biến hoặc toàn cầu của lớp. Thứ hai, bất kể chúng tôi chọn gì, chúng tôi vẫn cần nhập# Tuple packing with variable annotation syntax t: Tuple[int, ...] = [1, 2, 3] # or t: Tuple[int, ...] = 1, 2, 3 # This only works in Python 3.8+ # Tuple unpacking with variable annotation syntax header: str kind: int body: Optional[List[str]] header, kind, body = message
4. The choice of a good keyword is hard, e.g. it can’t be# Tuple packing with variable annotation syntax t: Tuple[int, ...] = [1, 2, 3] # or t: Tuple[int, ...] = 1, 2, 3 # This only works in Python 3.8+ # Tuple unpacking with variable annotation syntax header: str kind: int body: Optional[List[str]] header, kind, body = message
2 because that is way too common a variable name, and it can’t be# Tuple packing with variable annotation syntax t: Tuple[int, ...] = [1, 2, 3] # or t: Tuple[int, ...] = 1, 2, 3 # This only works in Python 3.8+ # Tuple unpacking with variable annotation syntax header: str kind: int body: Optional[List[str]] header, kind, body = message
3 if we want to use it for class variables or globals. Second, no matter what we choose, we’d still need a# Tuple packing with variable annotation syntax t: Tuple[int, ...] = [1, 2, 3] # or t: Tuple[int, ...] = 1, 2, 3 # This only works in Python 3.8+ # Tuple unpacking with variable annotation syntax header: str kind: int body: Optional[List[str]] header, kind, body = message
4 import. - Sử dụng
# Tuple packing with variable annotation syntax t: Tuple[int, ...] = [1, 2, 3] # or t: Tuple[int, ...] = 1, 2, 3 # This only works in Python 3.8+ # Tuple unpacking with variable annotation syntax header: str kind: int body: Optional[List[str]] header, kind, body = message
5 làm từ khóa: Đề xuất sẽ là:# Tuple packing with variable annotation syntax t: Tuple[int, ...] = [1, 2, 3] # or t: Tuple[int, ...] = 1, 2, 3 # This only works in Python 3.8+ # Tuple unpacking with variable annotation syntax header: str kind: int body: Optional[List[str]] header, kind, body = message
5 as a keyword: The proposal would be:path = None # type: Optional[str] # Path to module source
1Vấn đề với điều này là
# Tuple packing with variable annotation syntax t: Tuple[int, ...] = [1, 2, 3] # or t: Tuple[int, ...] = 1, 2, 3 # This only works in Python 3.8+ # Tuple unpacking with variable annotation syntax header: str kind: int body: Optional[List[str]] header, kind, body = message
5 có nghĩa là xác định chức năng của một số thế hệ lập trình viên python [và công cụ!], Và cũng sử dụng nó để xác định các biến không làm tăng độ rõ. [Mặc dù điều này tất nhiên là chủ quan.] - Sử dụng cú pháp dựa trên chức năng: Nó đã được đề xuất để chú thích các loại biến bằng cách sử dụng
# Tuple packing with variable annotation syntax t: Tuple[int, ...] = [1, 2, 3] # or t: Tuple[int, ...] = 1, 2, 3 # This only works in Python 3.8+ # Tuple unpacking with variable annotation syntax header: str kind: int body: Optional[List[str]] header, kind, body = message
7. Mặc dù cú pháp này làm giảm bớt một số vấn đề với các nhận xét loại như không có chú thích trong AST, nhưng nó không giải quyết các vấn đề khác như khả năng đọc và nó giới thiệu chi phí thời gian chạy có thể.: It was proposed to annotate types of variables using# Tuple packing with variable annotation syntax t: Tuple[int, ...] = [1, 2, 3] # or t: Tuple[int, ...] = 1, 2, 3 # This only works in Python 3.8+ # Tuple unpacking with variable annotation syntax header: str kind: int body: Optional[List[str]] header, kind, body = message
7. Although this syntax alleviates some problems with type comments like absence of the annotation in AST, it does not solve other problems such as readability and it introduces possible runtime overhead. - Cho phép các chú thích loại để giải nén tuple: Điều này gây ra sự mơ hồ: Nó không rõ câu nói này có nghĩa là gì: This causes ambiguity: it’s not clear what this statement means:
Có phải
# Tuple packing with variable annotation syntax t: Tuple[int, ...] = [1, 2, 3] # or t: Tuple[int, ...] = 1, 2, 3 # This only works in Python 3.8+ # Tuple unpacking with variable annotation syntax header: str kind: int body: Optional[List[str]] header, kind, body = message
8 và# Tuple packing with variable annotation syntax t: Tuple[int, ...] = [1, 2, 3] # or t: Tuple[int, ...] = 1, 2, 3 # This only works in Python 3.8+ # Tuple unpacking with variable annotation syntax header: str kind: int body: Optional[List[str]] header, kind, body = message
9 cả hai loạivar = value # type: annotation var: annotation; var = value var: annotation = value
0, hay chúng ta mong đợivar = value # type: annotation var: annotation; var = value var: annotation = value
0 sẽ là một loại hai mặt hàng được phân phối trên# Tuple packing with variable annotation syntax t: Tuple[int, ...] = [1, 2, 3] # or t: Tuple[int, ...] = 1, 2, 3 # This only works in Python 3.8+ # Tuple unpacking with variable annotation syntax header: str kind: int body: Optional[List[str]] header, kind, body = message
8 và# Tuple packing with variable annotation syntax t: Tuple[int, ...] = [1, 2, 3] # or t: Tuple[int, ...] = 1, 2, 3 # This only works in Python 3.8+ # Tuple unpacking with variable annotation syntax header: str kind: int body: Optional[List[str]] header, kind, body = message
9, hoặc có lẽ# Tuple packing with variable annotation syntax t: Tuple[int, ...] = [1, 2, 3] # or t: Tuple[int, ...] = 1, 2, 3 # This only works in Python 3.8+ # Tuple unpacking with variable annotation syntax header: str kind: int body: Optional[List[str]] header, kind, body = message
8 có loạia: int print[a] # raises NameError
5 và# Tuple packing with variable annotation syntax t: Tuple[int, ...] = [1, 2, 3] # or t: Tuple[int, ...] = 1, 2, 3 # This only works in Python 3.8+ # Tuple unpacking with variable annotation syntax header: str kind: int body: Optional[List[str]] header, kind, body = message
9 có loạivar = value # type: annotation var: annotation; var = value var: annotation = value
0 không? . - Hình thức được đặt ra
a: int print[a] # raises NameError
8 cho các chú thích: Nó được đưa lên trên Python-Ideas như một phương thuốc cho sự mơ hồ được đề cập ở trên, nhưng nó đã bị từ chối vì cú pháp như vậy sẽ là lông, lợi ích rất nhẹ và khả năng đọc sẽ kém.a: int print[a] # raises NameError
8 for annotations: It was brought up on python-ideas as a remedy for the above-mentioned ambiguity, but it was rejected since such syntax would be hairy, the benefits are slight, and the readability would be poor. - Cho phép chú thích trong các bài tập bị chuỗi: Điều này có vấn đề về sự mơ hồ và khả năng đọc tương tự như việc giải nén Tuple, ví dụ: trong: This has problems of ambiguity and readability similar to tuple unpacking, for example in:
path = None # type: Optional[str] # Path to module source
2Đó là mơ hồ, các loại
# Tuple packing with variable annotation syntax t: Tuple[int, ...] = [1, 2, 3] # or t: Tuple[int, ...] = 1, 2, 3 # This only works in Python 3.8+ # Tuple unpacking with variable annotation syntax header: str kind: int body: Optional[List[str]] header, kind, body = message
9 vàprimes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: ClassVar[Dict[str, int]] = {}
00 nên là gì? Ngoài ra dòng thứ hai rất khó phân tích. - Cho phép các chú thích trong tuyên bố
some_number: int # variable without initial value some_list: List[int] = [] # variable with initial value
2 vàsome_number: int # variable without initial value some_list: List[int] = [] # variable with initial value
1: Điều này đã bị từ chối bởi vì trongsome_number: int # variable without initial value some_list: List[int] = [] # variable with initial value
1, nó sẽ khiến cho việc phát hiện ra một điều không thể thực tế, và trongsome_number: int # variable without initial value some_list: List[int] = [] # variable with initial value
2, nó sẽ nhầm lẫn trình phân tích cú pháp Cpython LL [1].some_number: int # variable without initial value some_list: List[int] = [] # variable with initial value
2 andsome_number: int # variable without initial value some_list: List[int] = [] # variable with initial value
1 statement: This was rejected because insome_number: int # variable without initial value some_list: List[int] = [] # variable with initial value
1 it would make it hard to spot the actual iterable, and insome_number: int # variable without initial value some_list: List[int] = [] # variable with initial value
2 it would confuse the CPython’s LL[1] parser. - Đánh giá các chú thích cục bộ theo thời gian định nghĩa chức năng: Điều này đã bị Guido từ chối vì vị trí của chú thích cho thấy mạnh mẽ rằng nó trong cùng phạm vi với mã xung quanh. This has been rejected by Guido because the placement of the annotation strongly suggests that it’s in the same scope as the surrounding code.
- Lưu trữ các chú thích biến cũng trong phạm vi chức năng: Giá trị của việc có sẵn các chú thích tại địa phương là không đủ để bù đắp đáng kể chi phí tạo và điền từ điển trên mỗi cuộc gọi chức năng. The value of having the annotations available locally is just not enough to significantly offset the cost of creating and populating the dictionary on each function call.
- Khởi tạo các biến được chú thích mà không cần gán: Nó đã được đề xuất trên các iDeas Python để khởi tạo
# Tuple packing with variable annotation syntax t: Tuple[int, ...] = [1, 2, 3] # or t: Tuple[int, ...] = 1, 2, 3 # This only works in Python 3.8+ # Tuple unpacking with variable annotation syntax header: str kind: int body: Optional[List[str]] header, kind, body = message
8 trongprimes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: ClassVar[Dict[str, int]] = {}
06 đếnpath = None # type: Optional[str] # Path to module source
9 hoặc cho một hằng số đặc biệt bổ sung như JavaScript tựaprimes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: ClassVar[Dict[str, int]] = {}
08. Tuy nhiên, việc thêm một giá trị singleton khác vào ngôn ngữ sẽ cần phải được kiểm tra ở mọi nơi trong mã. Do đó, Guido chỉ nói rõ ràng về điều này. It was proposed on python-ideas to initialize# Tuple packing with variable annotation syntax t: Tuple[int, ...] = [1, 2, 3] # or t: Tuple[int, ...] = 1, 2, 3 # This only works in Python 3.8+ # Tuple unpacking with variable annotation syntax header: str kind: int body: Optional[List[str]] header, kind, body = message
8 inprimes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: ClassVar[Dict[str, int]] = {}
06 topath = None # type: Optional[str] # Path to module source
9 or to an additional special constant like Javascript’sprimes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: ClassVar[Dict[str, int]] = {}
08. However, adding yet another singleton value to the language would needed to be checked for everywhere in the code. Therefore, Guido just said plain “No” to this. - Thêm cũng
primes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: ClassVar[Dict[str, int]] = {}
09 vào mô -đun gõ: Điều này là dự phòng vì các biến thể hiện là cách phổ biến hơn các biến lớp. Việc sử dụng phổ biến hơn xứng đáng là mặc định.primes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: ClassVar[Dict[str, int]] = {}
09 to the typing module: This is redundant because instance variables are way more common than class variables. The more common usage deserves to be the default. - Chỉ cho phép các chú thích biến thể hiện trong các phương pháp: Vấn đề là nhiều phương thức
my_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.
4 thực hiện rất nhiều điều bên cạnh việc khởi tạo các biến thể hiện và sẽ khó hơn [đối với con người] để tìm tất cả các chú thích biến biến thể. Và đôi khimy_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.
4 được đưa vào các phương pháp trợ giúp hơn, vì vậy nó thậm chí còn khó khăn hơn để đuổi theo chúng. Đặt các chú thích biến thể hiện cùng nhau trong lớp giúp tìm thấy chúng dễ dàng hơn và giúp người đọc mã lần đầu tiên. The problem is that manymy_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.
4 methods do a lot of things besides initializing instance variables, and it would be harder [for a human] to find all the instance variable annotations. And sometimesmy_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.
4 is factored into more helper methods so it’s even harder to chase them down. Putting the instance variable annotations together in the class makes it easier to find them, and helps a first-time reader of the code. - Sử dụng cú pháp
primes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: ClassVar[Dict[str, int]] = {}
12 cho các biến lớp: Điều này sẽ yêu cầu trình phân tích cú pháp phức tạp hơn và từ khóaprimes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: ClassVar[Dict[str, int]] = {}
13 sẽ gây nhầm lẫn cho cú pháp cao cấp có đầu óc đơn giản. Dù sao chúng ta cần phải có các biến lớp lưu trữmy_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.
6 thànhsane_world: bool if 2+2 == 4: sane_world = True else: sane_world = False
0, vì vậy một cú pháp đơn giản hơn đã được chọn.primes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: ClassVar[Dict[str, int]] = {}
12 for class variables: This would require a more complicated parser and theprimes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: ClassVar[Dict[str, int]] = {}
13 keyword would confuse simple-minded syntax highlighters. Anyway we need to havemy_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.
6 store class variables tosane_world: bool if 2+2 == 4: sane_world = True else: sane_world = False
0, so a simpler syntax was chosen. - Quên về
my_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.
6 Hoàn toàn: Điều này đã được đề xuất vì MyPy dường như rất hợp nhau mà không có cách nào để phân biệt giữa các biến lớp và phiên bản. Nhưng trình kiểm tra loại có thể làm những điều hữu ích với thông tin bổ sung, ví dụ như các bài tập tình cờ cho một biến lớp thông qua phiên bản [sẽ tạo một biến thể hiện làm mờ biến lớp]. Nó cũng có thể gắn cờ các biến thể hiện với mặc định có thể thay đổi, một mối nguy hiểm nổi tiếng.my_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.
6 altogether: This was proposed since mypy seems to be getting along fine without a way to distinguish between class and instance variables. But a type checker can do useful things with the extra information, for example flag accidental assignments to a class variable via the instance [which would create an instance variable shadowing the class variable]. It could also flag instance variables with mutable defaults, a well-known hazard. - Sử dụng
primes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: ClassVar[Dict[str, int]] = {}
17 thay vìmy_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.
6: Lý do chính tại saomy_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.
6 tốt hơn là theo sau: nhiều thứ là thuộc tính lớp, ví dụ: Phương pháp, mô tả, v.v. nhưng chỉ các thuộc tính cụ thể là các biến lớp về mặt khái niệm [hoặc có thể là hằng số].primes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: ClassVar[Dict[str, int]] = {}
17 instead ofmy_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.
6: The main reason whymy_var: int my_var = 5 # Passes type check. other_var: int = 'a' # Flagged as error by type checker, # but OK at runtime.
6 is better is following: many things are class attributes, e.g. methods, descriptors, etc. But only specific attributes are conceptually class variables [or maybe constants]. - Không đánh giá các chú thích, coi chúng là chuỗi: điều này sẽ không phù hợp với hành vi của các chú thích chức năng luôn được đánh giá. Mặc dù điều này có thể được xem xét lại trong tương lai, nhưng nó đã được quyết định trong PEP 484 rằng đây sẽ phải là một PEP riêng biệt. This would be inconsistent with the behavior of function annotations that are always evaluated. Although this might be reconsidered in future, it was decided in PEP 484 that this would have to be a separate PEP.
- Chú thích các loại biến trong lớp DocString của lớp: Nhiều dự án đã sử dụng các quy ước khác nhau, thường không có nhiều tính nhất quán và nói chung mà không phù hợp với cú pháp chú thích PEP 484. Ngoài ra, điều này sẽ đòi hỏi một trình phân tích cú pháp tinh vi đặc biệt. Điều này, đến lượt nó, sẽ đánh bại mục đích của PEP - hợp tác với các công cụ kiểm tra loại bên thứ ba. Many projects already use various docstring conventions, often without much consistency and generally without conforming to the PEP 484 annotation syntax yet. Also this would require a special sophisticated parser. This, in turn, would defeat the purpose of the PEP – collaborating with the third party type checking tools.
- Thực hiện
sane_world: bool if 2+2 == 4: sane_world = True else: sane_world = False
0 như một mô tả: Điều này đã được đề xuất để cấm thiết lậpsane_world: bool if 2+2 == 4: sane_world = True else: sane_world = False
0 cho một cái gì đó không phải là từ điển hoặc không không. Guido đã từ chối ý tưởng này là không cần thiết; Thay vào đó, một kiểu mẫu sẽ được nâng lên nếu một nỗ lực được thực hiện để cập nhậtsane_world: bool if 2+2 == 4: sane_world = True else: sane_world = False
0 khi nó là bất cứ thứ gì khác ngoài ánh xạ.sane_world: bool if 2+2 == 4: sane_world = True else: sane_world = False
0 as a descriptor: This was proposed to prohibit settingsane_world: bool if 2+2 == 4: sane_world = True else: sane_world = False
0 to something non-dictionary or non-None. Guido has rejected this idea as unnecessary; instead a TypeError will be raised if an attempt is made to updatesane_world: bool if 2+2 == 4: sane_world = True else: sane_world = False
0 when it is anything other than a mapping. - Đối xử với các chú thích trần giống như toàn cầu hoặc không thuộc về: Đề xuất bị từ chối sẽ thích sự hiện diện của một chú thích mà không chuyển nhượng trong một cơ thể chức năng không nên liên quan đến bất kỳ đánh giá nào. Ngược lại, PEP ngụ ý rằng nếu mục tiêu phức tạp hơn một tên, thì phần tay trái của nó nên được đánh giá tại điểm xảy ra trong cơ thể chức năng, chỉ để thực thi nó được xác định. Ví dụ, trong ví dụ này: The rejected proposal would prefer that the presence of an annotation without assignment in a function body should not involve any evaluation. In contrast, the PEP implies that if the target is more complex than a single name, its “left-hand part” should be evaluated at the point where it occurs in the function body, just to enforce that it is defined. For example, in this example:
path = None # type: Optional[str] # Path to module source
3Tên
primes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: ClassVar[Dict[str, int]] = {}
23 nên được đánh giá, chỉ để nếu nó không được xác định [như có khả năng trong ví dụ này :-], lỗi sẽ bị bắt trong thời gian chạy. Điều này phù hợp hơn với những gì xảy ra khi có giá trị ban đầu, và do đó dự kiến sẽ dẫn đến ít bất ngờ hơn. .
Khả năng tương thích ngược
PEP này hoàn toàn tương thích ngược.
Thực hiện
Một triển khai cho Python 3.6 được tìm thấy trên github repo tại //github.com/ilevkivskyi/cpython/tree/pep-526
Bản quyền
Tài liệu này đã được đặt trong phạm vi công cộng.