Chú thích biến trong Python 3.6 là gì?


83

Python 3.6 sắp được phát hành. PEP 494 - Lịch phát hành Python 3.6 đề cập đến cuối tháng 12, vì vậy tôi đã xem qua Có gì mới trong Python 3.6 để thấy họ đề cập đến các chú thích biến :

PEP 484 đã giới thiệu tiêu chuẩn cho các chú thích kiểu của các tham số hàm, hay còn gọi là gợi ý kiểu. PEP này bổ sung cú pháp cho Python để chú thích các loại biến bao gồm biến lớp và biến phiên bản:

primes: List[int] = []

captain: str  # Note: no initial value!

class Starship:
     stats: Dict[str, int] = {}

Cũng như đối với chú thích hàm, trình thông dịch Python không đính kèm bất kỳ ý nghĩa cụ thể nào cho chú thích biến và chỉ lưu trữ chúng trong một thuộc tính đặc biệt __annotations__của một lớp hoặc mô-đun. Trái ngược với khai báo biến trong các ngôn ngữ được nhập 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 kiểu có cấu trúc cho các công cụ và thư viện của bên thứ ba thông qua cây cú pháp trừu tượng và __annotations__thuộc tính.

Vì vậy, từ những gì tôi đọc, chúng là một phần của gợi ý kiểu đến từ Python 3.5, được mô tả trong Gợi ý kiểu là gì trong Python 3.5 .

Tôi làm theo captain: strclass Starshipví dụ, nhưng không chắc chắn về cái cuối cùng: Làm thế nào primes: List[int] = []giải thích? Có phải nó đang xác định một danh sách trống sẽ chỉ cho phép các số nguyên?


9
Gợi ý loại không thực hiện bất kỳ kiểm tra loại nào. primes: List[int] = []chỉ là một danh sách trống như primes = []. Sự khác biệt là bạn đang khẳng định rằng primes có nghĩa là để chỉ chứa ints và các ứng dụng bên thứ 3 có thể gõ kiểm tra chương trình của bạn để xác minh tuyên bố này, nhưng khi bạn chạy mã trong bất kỳ thông dịch viên python đó chỉ giống như viết primes = [], và do đó làm primes: List[int] = []; primes.append("string")vẫn là có hiệu lực.
Bakuriu

2
@Bakuriu vâng, điểm tốt. Như Jim Fasarakis-Hilliard mô tả trong câu trả lời của anh ấy cho Gợi ý kiểu là gì trong Python 3.5 , tại sao lại nhập gợi ýGiúp người kiểm tra kiểu, trợ giúp tài liệu và giúp IDE phát triển các công cụ chính xác và mạnh mẽ hơn . Lấy từ PEP 526 - Cú pháp cho các chú thích biến , Python sẽ vẫn là một ngôn ngữ được nhập động và các tác giả không muốn đưa ra gợi ý kiểu bắt buộc, ngay cả theo quy ước .
fedorqui 'VẬY đừng làm hại nữa'.

1
Điều này có trả lời câu hỏi của bạn không? Gợi ý kiểu trong Python 3.5 là gì?
AMC

Câu trả lời:


46

Mọi thứ giữa :và the =là một gợi ý kiểu, vì vậy primesthực sự được định nghĩa là List[int], và ban đầu được đặt thành một danh sách trống (và statsban đầu là một từ điển trống, được định nghĩa là Dict[str, int]).

List[int]Dict[str, int]không phải là một phần của cú pháp tiếp theo, tuy nhiên, những cú pháp này đã được định nghĩa trong PEP gợi ý gõ Python 3.5. Các 3,6 PEP 526 - Cú pháp cho Variable Chú thích đề nghị chỉ định nghĩa cú pháp để đính kèm các gợi ý tương tự để biến; trước khi bạn chỉ có thể đính kèm gợi ý kiểu cho các biến có nhận xét (ví dụ primes = [] # List[int]).

Cả hai ListDictđều là loại Chung , cho biết rằng bạn có một danh sách hoặc ánh xạ từ điển với nội dung cụ thể (cụ thể).

Đối với List, chỉ có một 'đối số' (các phần tử trong [...]cú pháp), loại của mọi phần tử trong danh sách. Đối Dict, đối số đầu tiên là loại khóa và đối số thứ hai là loại giá trị. Vì vậy, tất cả các giá trị trong primesdanh sách đều là số nguyên và tất cả các cặp khóa-giá trị trong statstừ điển đều là (str, int)cặp, ánh xạ chuỗi thành số nguyên.

Xem phần typing.Listtyping.Dictđịnh nghĩa, phần Generics , cũng như PEP 483 - Lý thuyết về Gợi ý Loại .

Giống như gợi ý kiểu trên các hàm, việc sử dụng chúng là tùy chọn và cũng được coi là chú thích (miễn là có một đối tượng để đính kèm các gợi ý này, vì vậy các hình cầu trong mô-đun và thuộc tính trên các lớp, nhưng không phải cục bộ trong các hàm) mà bạn có thể xem xét nội dung thông qua __annotations__thuộc tính. Bạn có thể đính kèm thông tin tùy ý vào các chú thích này, bạn không bị giới hạn hoàn toàn trong việc nhập thông tin gợi ý.

Bạn có thể muốn đọc toàn bộ đề xuất ; nó chứa một số chức năng bổ sung ở trên và ngoài cú pháp mới; nó chỉ định khi nào các chú thích như vậy được đánh giá, cách giới thiệu chúng và cách khai báo một thứ gì đó dưới dạng thuộc tính lớp so với thuộc tính cá thể, chẳng hạn.


Tôi có thể coi gợi ý loại là một loại nhận xét "máy đọc được", vì chúng không ảnh hưởng đến cách mã chạy (ngoại trừ một obj.__annotations__thuộc tính) không?
iBug 27/09/18

1
@iBug: chú thích là những nhận xét mà máy có thể đọc được, trong chừng mực rằng những nhận xét đó vẫn là những chú thích mà con người có thể đọc được. :-)
Martijn Pieters

56

Chú thích biến là gì?

Các chú thích biến chỉ là bước tiếp theo từ các # typechú thích, như chúng đã được định nghĩa trong PEP 484; lý do đằng sau sự thay đổi này được nêu rõ trong phần tương ứng của PEP 526 .

Vì vậy, thay vì gợi ý loại với:

primes = []  # type: List[int]

Cú pháp mới đã được giới thiệu để cho phép chú thích trực tiếp kiểu với một phép gán biểu mẫu:

primes: List[int] = []

mà, như @Martijn đã chỉ ra, biểu thị một danh sách các số nguyên bằng cách sử dụng các kiểu có sẵn typingvà khởi tạo nó thành một danh sách trống.

Nó mang lại những thay đổi gì?

Thay đổi đầu tiên được giới thiệu là cú pháp mới cho phép bạn chú thích tên bằng một loại, độc lập sau :ký tự hoặc chú thích tùy chọn đồng thời gán giá trị cho nó:

annotated_assignment_stmt ::=  augtarget ":" expression ["=" expression]

Vì vậy, ví dụ trong câu hỏi:

   primes: List[int] = [ ]
#    ^        ^         ^
#  augtarget  |         |
#         expression    |
#                  expression (optionally initialize to empty list)

Các thay đổi bổ sung cũng được giới thiệu cùng với cú pháp mới; mô-đun và lớp hiện có một __annotations__thuộc tính (như các hàm đã có kể từ PEP 3107 - Chú thích hàm ) trong đó siêu dữ liệu kiểu được đính kèm:

from typing import get_type_hints  # grabs __annotations__

Bây giờ __main__.__annotations__giữ các kiểu đã khai báo:

>>> from typing import List, get_type_hints
>>> primes: List[int] = []
>>> captain: str
>>> import __main__
>>> get_type_hints(__main__)
{'primes': typing.List<~T>[int]}

captain hiện sẽ không hiển thị thông qua get_type_hints bởi vì get_type_hintschỉ trả về các loại cũng có thể được truy cập trên một mô-đun; tức là, nó cần một giá trị trước:

>>> captain = "Picard"
>>> get_type_hints(__main__)
{'primes': typing.List<~T>[int], 'captain': <class 'str'>}

Sử dụng print(__annotations__)sẽ hiển thị 'captain': <class 'str'>nhưng bạn thực sự không nên truy cập __annotations__trực tiếp.

Tương tự, đối với các lớp:

>>> get_type_hints(Starship)
ChainMap({'stats': typing.Dict<~KT, ~VT>[str, int]}, {})

Nơi một ChainMap được sử dụng để lấy các chú thích cho một lớp nhất định (nằm trong ánh xạ đầu tiên) và tất cả các chú thích được xác định trong các lớp cơ sở được tìm thấy trong nó mro(ánh xạ hệ quả, {}cho đối tượng).

Cùng với cú pháp mới, một ClassVarkiểu mới đã được thêm vào để biểu thị các biến lớp. Đúng vậy, statstrong ví dụ của bạn thực sự là một biến phiên bản , không phải a ClassVar.

Tôi có bị buộc phải sử dụng nó không?

Cũng như các gợi ý về kiểu từ PEP 484, những gợi ý này là hoàn toàn tùy chọn và được sử dụng chính cho các công cụ kiểm tra kiểu (và bất cứ thứ gì khác mà bạn có thể xây dựng dựa trên thông tin này). Đó là tạm thời khi phiên bản ổn định của Python 3.6 được phát hành nên các chỉnh sửa nhỏ có thể được bổ sung trong tương lai.

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.