Loại không liên kết Python
Duck-typing-self là khái niệm xác định loại self một cách linh hoạt trong thời gian chạy thay vì hạn chế rằng nó phải được liên kết với loại lớp cụ thể. Trong đoạn mã trên, không có chức năng thanh nào của Foo được gọi với một đối tượng ngẫu nhiên O
PEP 3107 đã giới thiệu cú pháp cho các chú thích hàm, nhưng ngữ nghĩa không được xác định một cách có chủ ý. Hiện tại đã có đủ cách sử dụng của bên thứ 3 để phân tích kiểu tĩnh mà cộng đồng sẽ được hưởng lợi từ vốn từ vựng tiêu chuẩn và các công cụ cơ bản trong thư viện tiêu chuẩn Show PEP này giới thiệu một mô-đun tạm thời để cung cấp các định nghĩa và công cụ tiêu chuẩn này, cùng với một số quy ước cho các tình huống không có chú thích Lưu ý rằng PEP này rõ ràng vẫn KHÔNG ngăn cản việc sử dụng các chú thích khác, cũng như không yêu cầu (hoặc cấm) bất kỳ quá trình xử lý chú thích cụ thể nào, ngay cả khi chúng tuân theo thông số kỹ thuật này. Nó chỉ đơn giản là cho phép phối hợp tốt hơn, như PEP 333 đã làm cho các khung web Ví dụ, đây là một hàm đơn giản có đối số và kiểu trả về được khai báo trong chú thích def greeting(name: str) -> str: return 'Hello ' + name Mặc dù các chú thích này có sẵn trong thời gian chạy thông qua thuộc tính def greeting(name: str) -> str: return 'Hello ' + name15 thông thường, không có kiểm tra loại nào xảy ra trong thời gian chạy. Thay vào đó, đề xuất giả định sự tồn tại của một trình kiểm tra loại ngoại tuyến riêng biệt mà người dùng có thể tự nguyện chạy qua mã nguồn của họ. Về cơ bản, một trình kiểm tra loại như vậy hoạt động như một kẻ nói dối rất mạnh mẽ. (Mặc dù người dùng cá nhân có thể sử dụng một trình kiểm tra tương tự trong thời gian chạy để thực thi Thiết kế theo hợp đồng hoặc tối ưu hóa JIT, nhưng những công cụ đó vẫn chưa hoàn thiện. ) Đề xuất được truyền cảm hứng mạnh mẽ bởi mypy. Ví dụ: kiểu “dãy số nguyên” có thể được viết là def greeting(name: str) -> str: return 'Hello ' + name16. Dấu ngoặc vuông có nghĩa là không cần thêm cú pháp mới vào ngôn ngữ. Ví dụ ở đây sử dụng loại tùy chỉnh def greeting(name: str) -> str: return 'Hello ' + name17, được nhập từ mô-đun Python thuần túy def greeting(name: str) -> str: return 'Hello ' + name14. Ký hiệu def greeting(name: str) -> str: return 'Hello ' + name16 hoạt động trong thời gian chạy bằng cách triển khai def greeting(name: str) -> str: return 'Hello ' + name20 trong siêu dữ liệu (nhưng ý nghĩa của nó chủ yếu là đối với trình kiểm tra loại ngoại tuyến) Hệ thống loại hỗ trợ các loại hợp nhất, loại chung và loại đặc biệt có tên def greeting(name: str) -> str: return 'Hello ' + name12 phù hợp với (i. e. có thể gán cho và từ) tất cả các loại. Tính năng thứ hai này được lấy từ ý tưởng gõ dần dần. Đánh máy dần dần và hệ thống đánh máy đầy đủ được giải thích trong PEP 483 Các cách tiếp cận khác mà chúng tôi đã vay mượn hoặc các cách tiếp cận của chúng tôi có thể được so sánh và đối chiếu được mô tả trong PEP 482 PEP 3107 đã thêm hỗ trợ cho các chú thích tùy ý trên các phần của định nghĩa hàm. Mặc dù sau đó không có ý nghĩa nào được gán cho các chú thích, nhưng luôn có một mục tiêu ngầm định để sử dụng chúng cho gợi ý loại, được liệt kê là trường hợp sử dụng đầu tiên có thể có trong PEP đã nói PEP này nhằm mục đích cung cấp một cú pháp tiêu chuẩn cho các chú thích kiểu, mở mã Python để phân tích và tái cấu trúc tĩnh dễ dàng hơn, kiểm tra kiểu thời gian chạy tiềm năng và (có lẽ, trong một số ngữ cảnh) tạo mã sử dụng thông tin kiểu Trong số các mục tiêu này, phân tích tĩnh là quan trọng nhất. Điều này bao gồm hỗ trợ cho các trình kiểm tra loại ngoại tuyến như mypy, cũng như cung cấp một ký hiệu chuẩn mà các IDE có thể sử dụng để hoàn thành và tái cấu trúc mã Mặc dù mô-đun nhập liệu được đề xuất sẽ chứa một số khối xây dựng để kiểm tra loại thời gian chạy – cụ thể là hàm def greeting(name: str) -> str: return 'Hello ' + name22 – các gói của bên thứ ba sẽ phải được phát triển để triển khai chức năng kiểm tra loại thời gian chạy cụ thể, ví dụ như sử dụng trình trang trí hoặc siêu dữ liệu. Sử dụng gợi ý loại để tối ưu hóa hiệu suất được để lại như một bài tập cho người đọc Cũng cần nhấn mạnh rằng Python sẽ vẫn là một ngôn ngữ được gõ động và các tác giả không muốn đưa ra các gợi ý kiểu bắt buộc, thậm chí theo quy ước Bất kỳ chức năng nào không có chú thích phải được coi là có loại chung nhất có thể hoặc bị bỏ qua bởi bất kỳ trình kiểm tra loại nào. Các chức năng với trình trang trí def greeting(name: str) -> str: return 'Hello ' + name23 nên được coi là không có chú thích Các hàm được kiểm tra được khuyến nghị nhưng không bắt buộc phải có chú thích cho tất cả các đối số và kiểu trả về. Đối với một hàm được kiểm tra, chú thích mặc định cho các đối số và cho kiểu trả về là def greeting(name: str) -> str: return 'Hello ' + name12. Một ngoại lệ là đối số đầu tiên của các phương thức thể hiện và lớp. Nếu nó không được chú thích, thì nó được giả định là có kiểu của lớp chứa đối với các phương thức thể hiện và một kiểu đối tượng kiểu tương ứng với đối tượng lớp chứa đối với các phương thức lớp. Ví dụ, trong lớp def greeting(name: str) -> str: return 'Hello ' + name25, đối số đầu tiên của một phương thức thể hiện có kiểu ngầm định là def greeting(name: str) -> str: return 'Hello ' + name25. In a class method, the precise type of the first argument cannot be represented using the available type notation (Note that the return type of def greeting(name: str) -> str: return 'Hello ' + name27 ought to be annotated with def greeting(name: str) -> str: return 'Hello ' + name28. The reason for this is subtle. If def greeting(name: str) -> str: return 'Hello ' + name27 assumed a return annotation of def greeting(name: str) -> str: return 'Hello ' + name28, would that mean that an argument-less, un-annotated def greeting(name: str) -> str: return 'Hello ' + name27 method should still be type-checked? Rather than leaving this ambiguous or introducing an exception to the exception, we simply say that def greeting(name: str) -> str: return 'Hello ' + name27 ought to have a return annotation; the default behavior is thus the same as for other methods. ) A type checker is expected to check the body of a checked function for consistency with the given annotations. The annotations may also be used to check correctness of calls appearing in other checked functions Type checkers are expected to attempt to infer as much information as necessary. The minimum requirement is to handle the builtin decorators def greeting(name: str) -> str: return 'Hello ' + name33, def greeting(name: str) -> str: return 'Hello ' + name34 and def greeting(name: str) -> str: return 'Hello ' + name35 The syntax leverages PEP 3107-style annotations with a number of extensions described in sections below. In its basic form, type hinting is used by filling function annotation slots with classes def greeting(name: str) -> str: return 'Hello ' + name This states that the expected type of the def greeting(name: str) -> str: return 'Hello ' + name36 argument is def greeting(name: str) -> str: return 'Hello ' + name37. Analogically, the expected return type is def greeting(name: str) -> str: return 'Hello ' + name37 Expressions whose type is a subtype of a specific argument type are also accepted for that argument Type hints may be built-in classes (including those defined in standard library or third-party extension modules), abstract base classes, types available in the def greeting(name: str) -> str: return 'Hello ' + name39 module, and user-defined classes (including those defined in the standard library or third-party modules) While annotations are normally the best format for type hints, there are times when it is more appropriate to represent them by a special comment, or in a separately distributed stub file. (See below for examples. ) Annotations must be valid expressions that evaluate without raising exceptions at the time the function is defined (but see below for forward references) Annotations should be kept simple or static analysis tools may not be able to interpret the values. For example, dynamically computed types are unlikely to be understood. (This is an intentionally somewhat vague requirement, specific inclusions and exclusions may be added to future versions of this PEP as warranted by the discussion. ) In addition to the above, the following special constructs defined below may be used. def greeting(name: str) -> str: return 'Hello ' + name40, def greeting(name: str) -> str: return 'Hello ' + name12, def greeting(name: str) -> str: return 'Hello ' + name42, def greeting(name: str) -> str: return 'Hello ' + name43, def greeting(name: str) -> str: return 'Hello ' + name44, all ABCs and stand-ins for concrete classes exported from def greeting(name: str) -> str: return 'Hello ' + name14 (e. g. def greeting(name: str) -> str: return 'Hello ' + name17 and def greeting(name: str) -> str: return 'Hello ' + name47), type variables, and type aliases All newly introduced names used to support features described in following sections (such as def greeting(name: str) -> str: return 'Hello ' + name12 and def greeting(name: str) -> str: return 'Hello ' + name42) are available in the def greeting(name: str) -> str: return 'Hello ' + name14 module When used in a type hint, the expression def greeting(name: str) -> str: return 'Hello ' + name40 is considered equivalent to def greeting(name: str) -> str: return 'Hello ' + name52 Type aliases are defined by simple variable assignments Url = str def retry(url: Url, retry_count: int) -> None: ... Note that we recommend capitalizing alias names, since they represent user-defined types, which (like user-defined classes) are typically spelled that way Type aliases may be as complex as type hints in annotations – anything that is acceptable as a type hint is acceptable in a type alias from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float] Điều này tương đương với from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]] Frameworks expecting callback functions of specific signatures might be type hinted using def greeting(name: str) -> str: return 'Hello ' + name53. Examples from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body It is possible to declare the return type of a callable without specifying the call signature by substituting a literal ellipsis (three dots) for the list of arguments def partial(func: Callable[..., str], *args) -> Callable[..., str]: # Body Note that there are no square brackets around the ellipsis. The arguments of the callback are completely unconstrained in this case (and keyword arguments are acceptable) Since using callbacks with keyword arguments is not perceived as a common use case, there is currently no support for specifying keyword arguments with def greeting(name: str) -> str: return 'Hello ' + name44. Similarly, there is no support for specifying callback signatures with a variable number of arguments of a specific type Because def greeting(name: str) -> str: return 'Hello ' + name55 does double-duty as a replacement for def greeting(name: str) -> str: return 'Hello ' + name56, def greeting(name: str) -> str: return 'Hello ' + name57 is implemented by deferring to def greeting(name: str) -> str: return 'Hello ' + name58. However, def greeting(name: str) -> str: return 'Hello ' + name59 is not supported Since type information about objects kept in containers cannot be statically inferred in a generic way, abstract base classes have been extended to support subscription to denote expected types for container elements. Example from typing import Mapping, Set def notify_by_email(employees: Set[Employee], overrides: Mapping[str, str]) -> None: ... Generics can be parameterized by using a new factory available in def greeting(name: str) -> str: return 'Hello ' + name14 called def greeting(name: str) -> str: return 'Hello ' + name61. Example from typing import Sequence, TypeVar T = TypeVar('T') # Declare type variable def first(l: Sequence[T]) -> T: # Generic function return l[0] In this case the contract is that the returned value is consistent with the elements held by the collection Biểu thức def greeting(name: str) -> str: return 'Hello ' + name62 phải luôn được gán trực tiếp cho một biến (không nên sử dụng biểu thức này như một phần của biểu thức lớn hơn). Đối số của def greeting(name: str) -> str: return 'Hello ' + name62 phải là một chuỗi bằng với tên biến mà nó được gán. Các biến loại không được xác định lại def greeting(name: str) -> str: return 'Hello ' + name61 hỗ trợ ràng buộc các loại tham số thành một tập cố định các loại có thể (lưu ý. những loại đó không thể được tham số hóa bởi các biến loại). Ví dụ: chúng ta có thể định nghĩa một biến loại chỉ nằm trong phạm vi của def greeting(name: str) -> str: return 'Hello ' + name37 và def greeting(name: str) -> str: return 'Hello ' + name66. Theo mặc định, một biến loại bao gồm tất cả các loại có thể. Ví dụ về ràng buộc một biến kiểu from typing import TypeVar, Text AnyStr = TypeVar('AnyStr', Text, bytes) def concat(x: AnyStr, y: AnyStr) -> AnyStr: return x + y Hàm def greeting(name: str) -> str: return 'Hello ' + name67 có thể được gọi với hai đối số def greeting(name: str) -> str: return 'Hello ' + name37 hoặc hai đối số def greeting(name: str) -> str: return 'Hello ' + name66, nhưng không được gọi với sự kết hợp của các đối số def greeting(name: str) -> str: return 'Hello ' + name37 và ________0____66 Nên có ít nhất hai ràng buộc, nếu có; Các kiểu con của các kiểu bị hạn chế bởi một biến kiểu nên được coi là các kiểu cơ sở được liệt kê rõ ràng tương ứng của chúng trong ngữ cảnh của biến kiểu. Hãy xem xét ví dụ này def greeting(name: str) -> str: return 'Hello ' + name0 Cuộc gọi hợp lệ nhưng biến loại def greeting(name: str) -> str: return 'Hello ' + name72 sẽ được đặt thành def greeting(name: str) -> str: return 'Hello ' + name37 chứ không phải def greeting(name: str) -> str: return 'Hello ' + name74. Trên thực tế, loại suy luận của giá trị trả về được gán cho def greeting(name: str) -> str: return 'Hello ' + name75 cũng sẽ là def greeting(name: str) -> str: return 'Hello ' + name37 Ngoài ra, def greeting(name: str) -> str: return 'Hello ' + name12 là một giá trị hợp lệ cho mọi biến loại. Hãy xem xét những điều sau đây def greeting(name: str) -> str: return 'Hello ' + name1 Điều này tương đương với việc bỏ qua ký hiệu chung và chỉ nói def greeting(name: str) -> str: return 'Hello ' + name78 Bạn có thể bao gồm một lớp cơ sở def greeting(name: str) -> str: return 'Hello ' + name79 để định nghĩa một lớp do người dùng định nghĩa là chung chung. Thí dụ def greeting(name: str) -> str: return 'Hello ' + name2 def greeting(name: str) -> str: return 'Hello ' + name80 làm lớp cơ sở định nghĩa rằng lớp def greeting(name: str) -> str: return 'Hello ' + name81 nhận một tham số kiểu duy nhất là def greeting(name: str) -> str: return 'Hello ' + name82. Điều này cũng làm cho def greeting(name: str) -> str: return 'Hello ' + name82 hợp lệ như một loại trong nội dung lớp Lớp cơ sở def greeting(name: str) -> str: return 'Hello ' + name79 sử dụng một siêu dữ liệu xác định def greeting(name: str) -> str: return 'Hello ' + name85 để def greeting(name: str) -> str: return 'Hello ' + name86 hợp lệ như một loại def greeting(name: str) -> str: return 'Hello ' + name3 Một loại chung có thể có bất kỳ số lượng biến loại nào và các biến loại có thể bị hạn chế. This is valid def greeting(name: str) -> str: return 'Hello ' + name4 Mỗi đối số biến loại cho def greeting(name: str) -> str: return 'Hello ' + name79 phải khác biệt. Điều này là không hợp lệ def greeting(name: str) -> str: return 'Hello ' + name5 Lớp cơ sở def greeting(name: str) -> str: return 'Hello ' + name80 là dư thừa trong các trường hợp đơn giản khi bạn phân lớp một số lớp chung khác và chỉ định các biến kiểu cho các tham số của nó def greeting(name: str) -> str: return 'Hello ' + name6 Định nghĩa lớp đó tương đương với def greeting(name: str) -> str: return 'Hello ' + name7 Bạn có thể sử dụng đa thừa kế với def greeting(name: str) -> str: return 'Hello ' + name79 def greeting(name: str) -> str: return 'Hello ' + name8 Phân lớp một lớp chung mà không chỉ định tham số loại giả định ____0_______12 cho mỗi vị trí. Trong ví dụ sau, def greeting(name: str) -> str: return 'Hello ' + name91 không phải là chung chung nhưng hoàn toàn kế thừa từ def greeting(name: str) -> str: return 'Hello ' + name92 def greeting(name: str) -> str: return 'Hello ' + name9 Siêu dữ liệu chung không được hỗ trợ Loại biến tuân theo quy tắc phân giải tên thông thường. Tuy nhiên, có một số trường hợp đặc biệt trong ngữ cảnh kiểm tra đánh máy tĩnh
Các lớp chung do người dùng định nghĩa có thể được khởi tạo. Giả sử chúng ta viết một lớp def greeting(name: str) -> str: return 'Hello ' + name93 kế thừa từ def greeting(name: str) -> str: return 'Hello ' + name80 Url = str def retry(url: Url, retry_count: int) -> None: ...6 Để tạo các phiên bản def greeting(name: str) -> str: return 'Hello ' + name93, bạn gọi def greeting(name: str) -> str: return 'Hello ' + name96 giống như đối với một lớp thông thường. Trong thời gian chạy, loại (lớp) của thể hiện sẽ là def greeting(name: str) -> str: return 'Hello ' + name93. Nhưng loại nào nó phải kiểm tra loại? . Nếu hàm tạo (_______0_______27 hoặc def greeting(name: str) -> str: return 'Hello ' + name99) sử dụng def greeting(name: str) -> str: return 'Hello ' + name82 trong chữ ký của nó và một giá trị đối số tương ứng được truyền vào, loại của (các) đối số tương ứng sẽ được thay thế. Mặt khác, def greeting(name: str) -> str: return 'Hello ' + name12 được giả định. Thí dụ Url = str def retry(url: Url, retry_count: int) -> None: ...7 Trong trường hợp loại được suy luận sử dụng Url = str def retry(url: Url, retry_count: int) -> None: ...02 nhưng loại dự định cụ thể hơn, bạn có thể sử dụng nhận xét loại (xem bên dưới) để buộc loại biến, e. g Url = str def retry(url: Url, retry_count: int) -> None: ...8 Ngoài ra, bạn có thể khởi tạo một loại bê tông cụ thể, e. g Url = str def retry(url: Url, retry_count: int) -> None: ...9 Lưu ý rằng loại (lớp) thời gian chạy của Url = str def retry(url: Url, retry_count: int) -> None: ...03 và Url = str def retry(url: Url, retry_count: int) -> None: ...04 vẫn chỉ là def greeting(name: str) -> str: return 'Hello ' + name93 – Url = str def retry(url: Url, retry_count: int) -> None: ...06 và Url = str def retry(url: Url, retry_count: int) -> None: ...07 là các đối tượng lớp có thể phân biệt được, nhưng lớp thời gian chạy của các đối tượng được tạo bằng cách khởi tạo chúng không ghi lại sự khác biệt. Hành vi này được gọi là "loại xóa"; . g. Java, TypeScript) Sử dụng các lớp chung (được tham số hóa hoặc không) để truy cập các thuộc tính sẽ dẫn đến lỗi kiểm tra kiểu. Bên ngoài phần định nghĩa lớp, thuộc tính lớp không thể được chỉ định và chỉ có thể được tra cứu bằng cách truy cập nó thông qua một thể hiện của lớp không có thuộc tính thể hiện có cùng tên from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]0 Các phiên bản chung của các tập hợp trừu tượng như Url = str def retry(url: Url, retry_count: int) -> None: ...08 hoặc def greeting(name: str) -> str: return 'Hello ' + name17 và các phiên bản chung của các lớp dựng sẵn – Url = str def retry(url: Url, retry_count: int) -> None: ...10, def greeting(name: str) -> str: return 'Hello ' + name47, Url = str def retry(url: Url, retry_count: int) -> None: ...12 và Url = str def retry(url: Url, retry_count: int) -> None: ...13 – không thể được khởi tạo. Tuy nhiên, các lớp con cụ thể do người dùng định nghĩa và các phiên bản chung của các bộ sưu tập cụ thể có thể được khởi tạo from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]1 Lưu ý rằng không nên nhầm lẫn giữa các loại tĩnh và các lớp thời gian chạy. Loại vẫn bị xóa trong trường hợp này và biểu thức trên chỉ là cách viết tắt của from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]2 Không nên sử dụng lớp được chỉ định (e. g. Url = str def retry(url: Url, retry_count: int) -> None: ...06) trực tiếp trong một biểu thức – sử dụng bí danh loại (e. g. Url = str def retry(url: Url, retry_count: int) -> None: ...15) thay vào đó được ưu tiên. (Đầu tiên, tạo lớp có chỉ số, e. g. Url = str def retry(url: Url, retry_count: int) -> None: ...06, có chi phí thời gian chạy. Thứ hai, sử dụng bí danh loại dễ đọc hơn. ) def greeting(name: str) -> str: return 'Hello ' + name80 chỉ có giá trị như một lớp cơ sở – nó không phải là một loại thích hợp. Tuy nhiên, các loại chung do người dùng xác định, chẳng hạn như Url = str def retry(url: Url, retry_count: int) -> None: ...18 từ ví dụ trên và các loại chung và ABC tích hợp sẵn, chẳng hạn như Url = str def retry(url: Url, retry_count: int) -> None: ...19 và Url = str def retry(url: Url, retry_count: int) -> None: ...20 đều hợp lệ cả dưới dạng loại và dưới dạng lớp cơ sở. Ví dụ: chúng ta có thể định nghĩa một lớp con của def greeting(name: str) -> str: return 'Hello ' + name47 chuyên về các đối số kiểu from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]3 Url = str def retry(url: Url, retry_count: int) -> None: ...22 là lớp con của Url = str def retry(url: Url, retry_count: int) -> None: ...23 và là lớp con của Url = str def retry(url: Url, retry_count: int) -> None: ...24 Nếu một lớp cơ sở chung có một biến kiểu làm đối số kiểu, thì điều này làm cho lớp đã định nghĩa trở nên chung. Ví dụ: chúng ta có thể định nghĩa một lớp Url = str def retry(url: Url, retry_count: int) -> None: ...25 chung có thể lặp lại và một bộ chứa from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]4 Bây giờ Url = str def retry(url: Url, retry_count: int) -> None: ...26 là một loại hợp lệ. Note that we can use def greeting(name: str) -> str: return 'Hello ' + name82 multiple times in the base class list, as long as we don’t use the same type variable def greeting(name: str) -> str: return 'Hello ' + name82 multiple times within Url = str def retry(url: Url, retry_count: int) -> None: ...29 Cũng xem xét ví dụ sau from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]5 Trong trường hợp này MyDict có một tham số duy nhất, T Siêu lớp được sử dụng bởi def greeting(name: str) -> str: return 'Hello ' + name79 là một lớp con của Url = str def retry(url: Url, retry_count: int) -> None: ...31. Một lớp chung có thể là một ABC bằng cách bao gồm các phương thức hoặc thuộc tính trừu tượng và các lớp chung cũng có thể có ABC làm lớp cơ sở mà không có xung đột siêu dữ liệu A type variable may specify an upper bound using Url = str def retry(url: Url, retry_count: int) -> None: ...32 (note: from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]6 Không thể kết hợp giới hạn trên với các ràng buộc kiểu (như trong def greeting(name: str) -> str: return 'Hello ' + name72 được sử dụng, xem ví dụ trước đó); Xét một lớp Url = str def retry(url: Url, retry_count: int) -> None: ...34 với một lớp con Url = str def retry(url: Url, retry_count: int) -> None: ...35. Bây giờ, giả sử chúng ta có một hàm với một đối số được chú thích bằng Url = str def retry(url: Url, retry_count: int) -> None: ...36. Chúng ta có được phép gọi hàm này với một biến kiểu Url = str def retry(url: Url, retry_count: int) -> None: ...37 làm đối số của nó không? . Nhưng trừ khi chúng ta biết nhiều hơn về chức năng này, bộ kiểm tra kiểu sẽ từ chối cuộc gọi như vậy. hàm có thể nối thêm một phiên bản Url = str def retry(url: Url, retry_count: int) -> None: ...34 vào danh sách, điều này sẽ vi phạm kiểu của biến trong trình gọi Hóa ra một đối số như vậy hoạt động trái ngược, trong khi câu trả lời trực quan (đúng trong trường hợp hàm không thay đổi đối số của nó. ) yêu cầu đối số hành động hiệp biến. Bạn có thể tìm thấy phần giới thiệu dài hơn về các khái niệm này trên Wikipedia và trong PEP 483; Theo mặc định, các loại chung được coi là bất biến trong tất cả các biến loại, điều đó có nghĩa là các giá trị cho các biến được chú thích với các loại như Url = str def retry(url: Url, retry_count: int) -> None: ...36 phải khớp chính xác với chú thích loại – không có lớp con hoặc siêu lớp nào của tham số loại (trong ví dụ này là Url = str def retry(url: Url, retry_count: int) -> None: ...34) được phép Để tạo thuận lợi cho việc khai báo các loại vùng chứa trong đó việc kiểm tra loại hiệp biến hoặc chống biến được chấp nhận, các biến loại chấp nhận các đối số từ khóa Url = str def retry(url: Url, retry_count: int) -> None: ...41 hoặc Url = str def retry(url: Url, retry_count: int) -> None: ...42. Nhiều nhất một trong số này có thể được thông qua. Các loại chung được xác định bằng các biến như vậy được coi là đồng biến hoặc chống biến trong biến tương ứng. Theo quy ước, nên sử dụng các tên kết thúc bằng Url = str def retry(url: Url, retry_count: int) -> None: ...43 cho các biến loại được xác định bằng Url = str def retry(url: Url, retry_count: int) -> None: ...41 và các tên kết thúc bằng Url = str def retry(url: Url, retry_count: int) -> None: ...45 cho biến được xác định bằng Url = str def retry(url: Url, retry_count: int) -> None: ...42 Một ví dụ điển hình liên quan đến việc xác định lớp vùng chứa bất biến (hoặc chỉ đọc) from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]7 Các lớp tập hợp chỉ đọc trong def greeting(name: str) -> str: return 'Hello ' + name14 đều được khai báo đồng biến trong biến kiểu của chúng (e. g. Url = str def retry(url: Url, retry_count: int) -> None: ...08 và def greeting(name: str) -> str: return 'Hello ' + name17). Các lớp tập hợp có thể thay đổi (e. g. Url = str def retry(url: Url, retry_count: int) -> None: ...50 và Url = str def retry(url: Url, retry_count: int) -> None: ...51) được khai báo là bất biến. Một ví dụ về loại trái ngược là loại Url = str def retry(url: Url, retry_count: int) -> None: ...52, trái ngược với loại đối số Url = str def retry(url: Url, retry_count: int) -> None: ...53 (xem bên dưới) Ghi chú. Hiệp phương sai hoặc chống phương sai không phải là thuộc tính của biến loại, mà là thuộc tính của lớp chung được xác định bằng biến này. Phương sai chỉ áp dụng cho các loại chung; . Cái sau chỉ nên được xác định bằng cách sử dụng các biến loại mà không có đối số từ khóa Url = str def retry(url: Url, retry_count: int) -> None: ...54 hoặc Url = str def retry(url: Url, retry_count: int) -> None: ...55. Ví dụ như sau cũng được from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]8 trong khi những điều sau đây bị cấm from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]9 PEP 3141 xác định tháp số của Python và mô-đun stdlib Url = str def retry(url: Url, retry_count: int) -> None: ...56 triển khai các ABC tương ứng ( Url = str def retry(url: Url, retry_count: int) -> None: ...57, Url = str def retry(url: Url, retry_count: int) -> None: ...58, Url = str def retry(url: Url, retry_count: int) -> None: ...59, Url = str def retry(url: Url, retry_count: int) -> None: ...60 và Url = str def retry(url: Url, retry_count: int) -> None: ...61). Có một số vấn đề với các ABC này, nhưng các lớp số cụ thể tích hợp sẵn Url = str def retry(url: Url, retry_count: int) -> None: ...62, Url = str def retry(url: Url, retry_count: int) -> None: ...63 và Url = str def retry(url: Url, retry_count: int) -> None: ...64 rất phổ biến (đặc biệt là hai lớp sau. -) Thay vì yêu cầu người dùng viết Url = str def retry(url: Url, retry_count: int) -> None: ...65 và sau đó sử dụng Url = str def retry(url: Url, retry_count: int) -> None: ...66, v.v. , PEP này đề xuất một lối tắt đơn giản gần như hiệu quả. khi một đối số được chú thích là có loại Url = str def retry(url: Url, retry_count: int) -> None: ...63, thì một đối số loại Url = str def retry(url: Url, retry_count: int) -> None: ...64 được chấp nhận; . Điều này không xử lý các lớp triển khai ABC tương ứng hoặc lớp Url = str def retry(url: Url, retry_count: int) -> None: ...72, nhưng chúng tôi tin rằng những trường hợp sử dụng đó cực kỳ hiếm Khi một gợi ý loại chứa các tên chưa được xác định, định nghĩa đó có thể được biểu thị dưới dạng một chuỗi ký tự, sẽ được giải quyết sau Một tình huống mà điều này thường xảy ra là định nghĩa của một lớp chứa, trong đó lớp được định nghĩa xuất hiện trong chữ ký của một số phương thức. Ví dụ: đoạn mã sau (bắt đầu triển khai cây nhị phân đơn giản) không hoạt động from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]0 Để giải quyết vấn đề này, chúng tôi viết from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]1 Chuỗi ký tự phải chứa một biểu thức Python hợp lệ (i. e. , Url = str def retry(url: Url, retry_count: int) -> None: ...73 phải là một đối tượng mã hợp lệ) và nó sẽ đánh giá mà không có lỗi sau khi mô-đun đã được tải đầy đủ. Không gian tên cục bộ và toàn cầu mà nó được đánh giá phải là cùng một không gian tên trong đó các đối số mặc định cho cùng một chức năng sẽ được đánh giá Hơn nữa, biểu thức phải được phân tích cú pháp dưới dạng gợi ý loại hợp lệ, tôi. e. , nó bị hạn chế bởi các quy tắc từ phần trên Ví dụ, được phép sử dụng các chuỗi ký tự như một phần của gợi ý loại from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]2 Một cách sử dụng phổ biến cho các tham chiếu chuyển tiếp là khi e. g. Các mô hình Django là cần thiết trong chữ ký. Thông thường, mỗi mô hình nằm trong một tệp riêng biệt và có các phương thức lấy đối số có loại liên quan đến các mô hình khác. Do cách nhập vòng tròn hoạt động trong Python, thường không thể nhập trực tiếp tất cả các mô hình cần thiết from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]3 Giả sử main được nhập trước, điều này sẽ không thành công với ImportError ở dòng Url = str def retry(url: Url, retry_count: int) -> None: ...74 trong models/b. py, đang được nhập từ models/a. py trước a đã xác định lớp A. Giải pháp là chuyển sang nhập chỉ theo mô-đun và tham chiếu các mô hình theo _module_ của chúng. _tên lớp from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]4 Vì việc chấp nhận một tập hợp nhỏ, hạn chế các loại dự kiến cho một đối số là phổ biến, nên có một nhà máy đặc biệt mới có tên là def greeting(name: str) -> str: return 'Hello ' + name42. Thí dụ from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]5 Một loại được tính bởi Url = str def retry(url: Url, retry_count: int) -> None: ...76 là siêu kiểu của tất cả các loại Url = str def retry(url: Url, retry_count: int) -> None: ...77, Url = str def retry(url: Url, retry_count: int) -> None: ...78, v.v. , so that a value that is a member of one of these types is acceptable for an argument annotated by Url = str def retry(url: Url, retry_count: int) -> None: ...76 Một trường hợp phổ biến của các loại liên kết là các loại tùy chọn. Theo mặc định, def greeting(name: str) -> str: return 'Hello ' + name40 là một giá trị không hợp lệ cho bất kỳ loại nào, trừ khi giá trị mặc định của def greeting(name: str) -> str: return 'Hello ' + name40 đã được cung cấp trong định nghĩa hàm. ví dụ from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]6 Để viết tắt cho Url = str def retry(url: Url, retry_count: int) -> None: ...82, bạn có thể viết Url = str def retry(url: Url, retry_count: int) -> None: ...83; from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]7 Phiên bản trước đây của PEP này cho phép người kiểm tra loại giả sử một loại tùy chọn khi giá trị mặc định là def greeting(name: str) -> str: return 'Hello ' + name40, như trong mã này from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]8 Điều này sẽ được coi là tương đương với from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]9 Đây không còn là hành vi được đề xuất. Type checkers should move towards requiring the optional type to be made explicit Một thể hiện đơn lẻ thường được sử dụng để đánh dấu một số điều kiện đặc biệt, cụ thể là trong các tình huống mà def greeting(name: str) -> str: return 'Hello ' + name40 cũng là một giá trị hợp lệ cho một biến. Thí dụ from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body0 Để cho phép nhập chính xác trong các tình huống như vậy, người dùng nên sử dụng loại def greeting(name: str) -> str: return 'Hello ' + name42 kết hợp với lớp Url = str def retry(url: Url, retry_count: int) -> None: ...87 do thư viện tiêu chuẩn cung cấp, để có thể bắt lỗi loại một cách tĩnh from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body1 Since the subclasses of Url = str def retry(url: Url, retry_count: int) -> None: ...88 cannot be further subclassed, the type of variable def greeting(name: str) -> str: return 'Hello ' + name75 can be statically inferred in all branches of the above example. Cách tiếp cận tương tự được áp dụng nếu cần nhiều hơn một đối tượng đơn lẻ. người ta có thể sử dụng một phép liệt kê có nhiều hơn một giá trị from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body2 Một loại đặc biệt của loại là def greeting(name: str) -> str: return 'Hello ' + name12. Mọi loại đều nhất quán với def greeting(name: str) -> str: return 'Hello ' + name12. It can be considered a type that has all values and all methods. Note that def greeting(name: str) -> str: return 'Hello ' + name12 and builtin type Url = str def retry(url: Url, retry_count: int) -> None: ...94 are completely different When the type of a value is Url = str def retry(url: Url, retry_count: int) -> None: ...94, the type checker will reject almost all operations on it, and assigning it to a variable (or using it as a return value) of a more specialized type is a type error. On the other hand, when a value has type def greeting(name: str) -> str: return 'Hello ' + name12, the type checker will allow all operations on it, and a value of type def greeting(name: str) -> str: return 'Hello ' + name12 can be assigned to a variable (or used as a return value) of a more constrained type Một tham số chức năng không có chú thích được coi là có chú thích với def greeting(name: str) -> str: return 'Hello ' + name12. Nếu một loại chung được sử dụng mà không chỉ định tham số loại, thì chúng được giả định là def greeting(name: str) -> str: return 'Hello ' + name12 from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body3 Quy tắc này cũng áp dụng cho def greeting(name: str) -> str: return 'Hello ' + name43, trong ngữ cảnh chú thích, nó tương đương với from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]01 và ngược lại, với from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]02. Đồng thời, một def greeting(name: str) -> str: return 'Hello ' + name44 trần trong một chú thích tương đương với from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]04 và ngược lại, với def greeting(name: str) -> str: return 'Hello ' + name56 from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body4 Mô-đun def greeting(name: str) -> str: return 'Hello ' + name14 cung cấp một loại đặc biệt def greeting(name: str) -> str: return 'Hello ' + name13 để chú thích các chức năng không bao giờ trở lại bình thường. Ví dụ, một chức năng đưa ra một ngoại lệ vô điều kiện from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body5 Chú thích def greeting(name: str) -> str: return 'Hello ' + name13 được sử dụng cho các chức năng như from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]10. Trình kiểm tra kiểu tĩnh sẽ đảm bảo rằng các hàm được chú thích là trả về def greeting(name: str) -> str: return 'Hello ' + name13 thực sự không bao giờ trả về, dù ngầm hay rõ ràng from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body6 Người kiểm tra cũng sẽ nhận ra rằng mã sau khi gọi các chức năng đó là không thể truy cập được và sẽ hoạt động tương ứng from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body7 Loại def greeting(name: str) -> str: return 'Hello ' + name13 chỉ hợp lệ dưới dạng chú thích trả về của các hàm và được coi là lỗi nếu nó xuất hiện ở các vị trí khác from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body8 Đôi khi bạn muốn nói về các đối tượng lớp, cụ thể là các đối tượng lớp kế thừa từ một lớp nhất định. Điều này có thể được đánh vần là from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]13 trong đó from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]14 là một lớp học. Làm rõ. trong khi from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]14 (khi được sử dụng làm chú thích) đề cập đến các thể hiện của lớp from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]14, thì from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]13 đề cập đến các lớp con của from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]14. (Đây là sự khác biệt tương tự như giữa Url = str def retry(url: Url, retry_count: int) -> None: ...94 và from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]20. ) Ví dụ: giả sử chúng ta có các lớp sau from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body9 Và giả sử chúng ta có một hàm tạo một thể hiện của một trong các lớp này nếu bạn truyền cho nó một đối tượng lớp def partial(func: Callable[..., str], *args) -> Callable[..., str]: # Body0 Nếu không có from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]21, điều tốt nhất chúng tôi có thể làm để chú thích from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]22 sẽ là def partial(func: Callable[..., str], *args) -> Callable[..., str]: # Body1 Tuy nhiên, sử dụng from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]21 và biến loại có giới hạn trên, chúng ta có thể làm tốt hơn nhiều def partial(func: Callable[..., str], *args) -> Callable[..., str]: # Body2 Bây giờ, khi chúng ta gọi from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]22 với một phân lớp cụ thể là from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]25, trình kiểm tra loại sẽ suy ra loại kết quả chính xác def partial(func: Callable[..., str], *args) -> Callable[..., str]: # Body3 Giá trị tương ứng với from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]13 phải là một đối tượng lớp thực sự là một kiểu con của from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]14, không phải là một dạng đặc biệt. Nói cách khác, trong ví dụ trên gọi e. g. from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]28 bị trình kiểm tra loại từ chối (ngoài việc không thành công trong thời gian chạy vì bạn không thể khởi tạo liên kết) Lưu ý rằng việc sử dụng tập hợp các lớp làm tham số cho from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]21 là hợp pháp, như trong def partial(func: Callable[..., str], *args) -> Callable[..., str]: # Body4 Tuy nhiên, đối số thực tế được truyền trong thời gian chạy vẫn phải là một đối tượng lớp cụ thể, e. g. trong ví dụ trên def partial(func: Callable[..., str], *args) -> Callable[..., str]: # Body5 from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]30 cũng được hỗ trợ (xem bên dưới để biết ý nghĩa của nó) from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]31 trong đó def greeting(name: str) -> str: return 'Hello ' + name82 là biến kiểu được cho phép khi chú thích đối số đầu tiên của phương thức lớp (xem phần liên quan) Bất kỳ cấu trúc đặc biệt nào khác như def greeting(name: str) -> str: return 'Hello ' + name43 hoặc def greeting(name: str) -> str: return 'Hello ' + name44 đều không được phép làm đối số cho from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]35 Có một số lo ngại với tính năng này. ví dụ: khi from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]22 gọi from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]37, điều này ngụ ý rằng tất cả các lớp con của from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]25 phải hỗ trợ điều này trong chữ ký hàm tạo của chúng. Tuy nhiên, đây không phải là duy nhất đối với from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]21. các phương thức lớp có mối quan tâm tương tự. Trình kiểm tra loại phải gắn cờ vi phạm các giả định đó, nhưng theo mặc định, hàm tạo khớp với chữ ký của hàm tạo trong lớp cơ sở được chỉ định ( from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]25 trong ví dụ trên) nên được phép. Một chương trình chứa hệ thống phân cấp lớp phức tạp hoặc có thể mở rộng cũng có thể xử lý việc này bằng cách sử dụng phương thức lớp xuất xưởng. Bản sửa đổi trong tương lai của PEP này có thể đưa ra những cách tốt hơn để giải quyết những mối lo ngại này Khi from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]35 được tham số hóa, nó yêu cầu chính xác một tham số. Đồng bằng from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]35 không có dấu ngoặc đơn tương đương với from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]30 và điều này đến lượt nó tương đương với from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]20 (gốc của hệ thống phân cấp siêu dữ liệu của Python). Sự tương đương này cũng thúc đẩy tên, from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]35, trái ngược với các lựa chọn thay thế như from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]46 hoặc from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]47, được đề xuất trong khi tính năng này đang được thảo luận; . g. Url = str def retry(url: Url, retry_count: int) -> None: ...10 và from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]49 Đối với hành vi của from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]30 (hoặc from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]35 hoặc from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]20), việc truy cập các thuộc tính của một biến với loại này chỉ cung cấp các thuộc tính và phương thức được xác định bởi from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]20 (ví dụ: from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]54 và from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]55). Một biến như vậy có thể được gọi với các đối số tùy ý và kiểu trả về là def greeting(name: str) -> str: return 'Hello ' + name12 from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]35 là biến thể trong tham số của nó, bởi vì from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]58 là một kiểu con của from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]59 def partial(func: Callable[..., str], *args) -> Callable[..., str]: # Body6 Trong hầu hết các trường hợp, đối số đầu tiên của các phương thức lớp và thể hiện không cần phải được chú thích và nó được giả định là có kiểu của lớp chứa đối với các phương thức thể hiện và một kiểu đối tượng kiểu tương ứng với đối tượng lớp chứa đối với các phương thức lớp. Ngoài ra, đối số đầu tiên trong một phương thức thể hiện có thể được chú thích bằng một biến kiểu. Trong trường hợp này, kiểu trả về có thể sử dụng cùng một biến kiểu, do đó làm cho phương thức đó trở thành một hàm chung. Ví dụ def partial(func: Callable[..., str], *args) -> Callable[..., str]: # Body7 Điều tương tự cũng áp dụng cho các phương thức lớp sử dụng from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]21 trong chú thích của đối số đầu tiên def partial(func: Callable[..., str], *args) -> Callable[..., str]: # Body8 Lưu ý rằng một số trình kiểm tra loại có thể áp dụng các hạn chế đối với việc sử dụng này, chẳng hạn như yêu cầu giới hạn trên thích hợp cho biến loại được sử dụng (xem ví dụ) Trình kiểm tra loại dự kiến sẽ hiểu các kiểm tra nền tảng và phiên bản đơn giản, e. g def partial(func: Callable[..., str], *args) -> Callable[..., str]: # Body9 Đừng mong đợi một người kiểm tra hiểu được những điều khó hiểu như from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]61 Đôi khi, có mã phải được trình kiểm tra loại (hoặc các công cụ phân tích tĩnh khác) nhìn thấy nhưng không được thực thi. Đối với những tình huống như vậy, mô-đun def greeting(name: str) -> str: return 'Hello ' + name14 xác định một hằng số, from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]63, được coi là from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]64 trong quá trình kiểm tra loại (hoặc phân tích tĩnh khác) nhưng lại là from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]65 trong thời gian chạy. Thí dụ from typing import Mapping, Set def notify_by_email(employees: Set[Employee], overrides: Mapping[str, str]) -> None: ...0 (Lưu ý rằng chú thích loại phải được đặt trong dấu ngoặc kép, làm cho nó trở thành "tham chiếu chuyển tiếp", để ẩn tham chiếu from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]66 khỏi thời gian chạy trình thông dịch. Trong bình luận from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]67 không cần trích dẫn. ) Cách tiếp cận này cũng có thể hữu ích để xử lý các chu kỳ nhập Danh sách đối số tùy ý cũng có thể được chú thích kiểu, để định nghĩa from typing import Mapping, Set def notify_by_email(employees: Set[Employee], overrides: Mapping[str, str]) -> None: ...1 là chấp nhận được và nó có nghĩa là, e. g. , tất cả các lệnh gọi hàm sau đây có các loại đối số hợp lệ from typing import Mapping, Set def notify_by_email(employees: Set[Employee], overrides: Mapping[str, str]) -> None: ...2 Trong thân hàm from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]68, kiểu của biến from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]69 được suy ra là from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]70 và kiểu của biến from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]71 là from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]72 Trong sơ khai, có thể hữu ích khi khai báo một đối số là có giá trị mặc định mà không chỉ định giá trị mặc định thực tế. Ví dụ from typing import Mapping, Set def notify_by_email(employees: Set[Employee], overrides: Mapping[str, str]) -> None: ...3 Giá trị mặc định sẽ như thế nào? Trong những trường hợp như vậy, giá trị mặc định có thể được chỉ định dưới dạng dấu chấm lửng, tôi. e. ví dụ trên đúng nghĩa là những gì bạn sẽ viết Một số hàm được thiết kế để chỉ lấy các đối số của chúng theo vị trí và yêu cầu người gọi chúng không bao giờ sử dụng tên của đối số để cung cấp đối số đó theo từ khóa. Tất cả các đối số có tên bắt đầu bằng from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]76 được coi là chỉ có vị trí, trừ khi tên của chúng cũng kết thúc bằng from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]76 from typing import Mapping, Set def notify_by_email(employees: Set[Employee], overrides: Mapping[str, str]) -> None: ...4 Kiểu trả về của các hàm tạo có thể được chú thích bằng kiểu chung from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]78 được cung cấp bởi mô-đun from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]79 from typing import Mapping, Set def notify_by_email(employees: Set[Employee], overrides: Mapping[str, str]) -> None: ...5 Các coroutine được giới thiệu trong PEP 492 được chú thích với cú pháp giống như các hàm thông thường. Tuy nhiên, chú thích kiểu trả về tương ứng với kiểu của biểu thức from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]80, không phải kiểu coroutine from typing import Mapping, Set def notify_by_email(employees: Set[Employee], overrides: Mapping[str, str]) -> None: ...6 Mô-đun from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]79 cung cấp một phiên bản chung của ABC from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]82 để chỉ định các nội dung có thể chờ đợi cũng hỗ trợ các phương thức Url = str def retry(url: Url, retry_count: int) -> None: ...53 và from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]84. Phương sai và thứ tự của các biến loại tương ứng với biến của Url = str def retry(url: Url, retry_count: int) -> None: ...52, cụ thể là from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]86 chẳng hạn from typing import Mapping, Set def notify_by_email(employees: Set[Employee], overrides: Mapping[str, str]) -> None: ...7 Mô-đun này cũng cung cấp các ABC chung from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]87, from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]88 và from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]89 cho các tình huống không thể chỉ định các loại chính xác hơn from typing import Mapping, Set def notify_by_email(employees: Set[Employee], overrides: Mapping[str, str]) -> None: ...8 Một số trường hợp sử dụng hiện có hoặc tiềm năng cho chú thích chức năng tồn tại, không tương thích với gợi ý loại. Những điều này có thể gây nhầm lẫn cho trình kiểm tra kiểu tĩnh. Tuy nhiên, vì các chú thích gợi ý kiểu không có hành vi trong thời gian chạy (ngoài việc đánh giá biểu thức chú thích và lưu trữ các chú thích trong thuộc tính def greeting(name: str) -> str: return 'Hello ' + name15 của đối tượng hàm), điều này không làm cho chương trình không chính xác – nó chỉ có thể khiến trình kiểm tra kiểu đưa ra các cảnh báo giả mạo Để đánh dấu các phần của chương trình không được bao phủ bởi gợi ý loại, bạn có thể sử dụng một hoặc nhiều cách sau
Để biết thêm chi tiết xem các phần sau Để có khả năng tương thích tối đa với kiểm tra loại ngoại tuyến, cuối cùng, có thể nên thay đổi các giao diện dựa trên chú thích để chuyển sang một cơ chế khác, chẳng hạn như trình trang trí. Trong Trăn 3. 5 không có áp lực để làm điều này, tuy nhiên. Xem thêm cuộc thảo luận dài hơn bên dưới PEP này không hỗ trợ cú pháp hạng nhất để đánh dấu rõ ràng các biến là thuộc một loại cụ thể. Để giúp suy luận kiểu trong các trường hợp phức tạp, có thể sử dụng nhận xét có định dạng sau from typing import Mapping, Set def notify_by_email(employees: Set[Employee], overrides: Mapping[str, str]) -> None: ...9 Loại nhận xét nên được đặt trên dòng cuối cùng của câu lệnh có chứa định nghĩa biến. Chúng cũng có thể được đặt trên câu lệnh from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]94 và câu lệnh from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]95, ngay sau dấu hai chấm Ví dụ về nhận xét loại trên câu lệnh from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]94 và from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]95 from typing import Sequence, TypeVar T = TypeVar('T') # Declare type variable def first(l: Sequence[T]) -> T: # Generic function return l[0]0 Trong sơ khai, có thể hữu ích khi khai báo sự tồn tại của một biến mà không cho nó một giá trị ban đầu. Điều này có thể được thực hiện bằng cách sử dụng cú pháp chú thích biến PEP 526 from typing import Sequence, TypeVar T = TypeVar('T') # Declare type variable def first(l: Sequence[T]) -> T: # Generic function return l[0]1 Cú pháp trên được chấp nhận trong sơ khai cho tất cả các phiên bản Python. Tuy nhiên, trong mã không còn sơ khai cho các phiên bản Python 3. 5 trở về trước có trường hợp đặc biệt from typing import Sequence, TypeVar T = TypeVar('T') # Declare type variable def first(l: Sequence[T]) -> T: # Generic function return l[0]2 Người kiểm tra loại không nên phàn nàn về điều này (mặc dù giá trị def greeting(name: str) -> str: return 'Hello ' + name40 không khớp với loại đã cho), họ cũng không nên thay đổi loại được suy luận thành from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]99 (bất chấp quy tắc thực hiện điều này đối với các đối số được chú thích có giá trị mặc định là def greeting(name: str) -> str: return 'Hello ' + name40). Giả định ở đây là mã khác sẽ đảm bảo rằng biến được cung cấp một giá trị của loại phù hợp và tất cả các cách sử dụng có thể giả định rằng biến có loại đã cho Nhận xét from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]91 phải được đặt trên dòng liên quan đến lỗi from typing import Sequence, TypeVar T = TypeVar('T') # Declare type variable def first(l: Sequence[T]) -> T: # Generic function return l[0]3 Một nhận xét from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]91 trên một dòng ở đầu tệp, trước bất kỳ chuỗi tài liệu, nhập hoặc mã thực thi nào khác, tắt tất cả các lỗi trong tệp. Các dòng trống và các nhận xét khác, chẳng hạn như các dòng shebang và cookie mã hóa, có thể đứng trước nhận xét from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]91 Trong một số trường hợp, có thể cần các công cụ linting hoặc các chú thích khác trên cùng một dòng với chú thích loại. Trong những trường hợp này, loại nhận xét phải ở trước các nhận xét khác và đánh dấu linting
Nếu gợi ý kiểu nói chung hữu ích, một cú pháp để gõ biến có thể được cung cấp trong phiên bản Python trong tương lai. (CẬP NHẬT. Cú pháp này đã được thêm vào Python 3. 6 đến PEP 526. ) Đôi khi trình kiểm tra loại có thể cần một loại gợi ý khác. lập trình viên có thể biết rằng một biểu thức thuộc loại bị ràng buộc hơn so với trình kiểm tra loại có thể suy ra. Ví dụ from typing import Sequence, TypeVar T = TypeVar('T') # Declare type variable def first(l: Sequence[T]) -> T: # Generic function return l[0]4 Một số trình kiểm tra loại có thể không thể suy luận rằng loại from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]04 là def greeting(name: str) -> str: return 'Hello ' + name37 và chỉ suy ra Url = str def retry(url: Url, retry_count: int) -> None: ...94 hoặc def greeting(name: str) -> str: return 'Hello ' + name12, nhưng chúng tôi biết rằng (nếu mã đạt đến điểm đó) thì đó phải là một chuỗi. Cuộc gọi from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]08 cho người kiểm tra loại biết rằng chúng tôi tự tin rằng loại def greeting(name: str) -> str: return 'Hello ' + name75 là from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]10. Trong thời gian chạy, một phép truyền luôn trả về biểu thức không thay đổi – nó không kiểm tra loại và nó không chuyển đổi hoặc ép buộc giá trị Diễn viên khác với nhận xét loại (xem phần trước). Khi sử dụng nhận xét loại, trình kiểm tra loại vẫn phải xác minh rằng loại được suy luận phù hợp với loại đã nêu. Khi sử dụng ép kiểu, người kiểm tra kiểu nên tin tưởng người lập trình một cách mù quáng. Ngoài ra, các phép ép kiểu có thể được sử dụng trong các biểu thức, trong khi các nhận xét kiểu chỉ áp dụng cho các bài tập Cũng có những tình huống mà một lập trình viên có thể muốn tránh các lỗi logic bằng cách tạo các lớp đơn giản. Ví dụ from typing import Sequence, TypeVar T = TypeVar('T') # Declare type variable def first(l: Sequence[T]) -> T: # Generic function return l[0]5 Tuy nhiên, cách tiếp cận này giới thiệu một chi phí thời gian chạy. Để tránh điều này, from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]79 cung cấp hàm trợ giúp from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]12 để tạo các kiểu duy nhất đơn giản với chi phí thời gian chạy gần như bằng không. Đối với trình kiểm tra kiểu tĩnh, from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]13 gần tương đương với định nghĩa from typing import Sequence, TypeVar T = TypeVar('T') # Declare type variable def first(l: Sequence[T]) -> T: # Generic function return l[0]6 Trong thời gian chạy, from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]14 trả về một hàm giả chỉ trả về đối số của nó. Trình kiểm tra loại yêu cầu chuyển kiểu rõ ràng từ Url = str def retry(url: Url, retry_count: int) -> None: ...64 trong đó dự kiến là from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]16, trong khi chuyển kiểu ngầm định từ from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]16 trong đó dự kiến là Url = str def retry(url: Url, retry_count: int) -> None: ...64. ví dụ from typing import Sequence, TypeVar T = TypeVar('T') # Declare type variable def first(l: Sequence[T]) -> T: # Generic function return l[0]7 from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]12 chấp nhận chính xác hai đối số. một tên cho loại duy nhất mới và một lớp cơ sở. Cái sau phải là một lớp thích hợp (tôi. e. , không phải là cấu trúc kiểu như def greeting(name: str) -> str: return 'Hello ' + name42, v.v. ) hoặc một loại duy nhất khác được tạo bằng cách gọi from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]12. Hàm được trả về bởi from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]12 chỉ chấp nhận một đối số; . Thí dụ from typing import Sequence, TypeVar T = TypeVar('T') # Declare type variable def first(l: Sequence[T]) -> T: # Generic function return l[0]8 Cả from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]23 và from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]24, cũng như việc phân lớp con sẽ không thành công đối với from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]14 vì các đối tượng hàm không hỗ trợ các thao tác này Các tệp sơ khai là các tệp chứa gợi ý loại chỉ được sử dụng bởi trình kiểm tra loại, không phải trong thời gian chạy. There are several use cases for stub files
Các tệp sơ khai có cú pháp giống như các mô-đun Python thông thường. Có một tính năng của mô-đun def greeting(name: str) -> str: return 'Hello ' + name14 khác trong tệp sơ khai. người trang trí from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]27 được mô tả bên dưới Trình kiểm tra kiểu chỉ nên kiểm tra chữ ký hàm trong tệp sơ khai; Trình kiểm tra loại phải có đường dẫn tìm kiếm có thể định cấu hình cho các tệp sơ khai. Nếu một tệp sơ khai được tìm thấy, trình kiểm tra loại sẽ không đọc mô-đun “thực” tương ứng Mặc dù các tệp sơ khai là các mô-đun Python hợp lệ về mặt cú pháp, nhưng chúng sử dụng phần mở rộng from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]29 để có thể duy trì các tệp sơ khai trong cùng thư mục với mô-đun thực tương ứng. Điều này cũng củng cố quan điểm rằng không nên có hành vi thời gian chạy đối với các tệp sơ khai Ghi chú bổ sung về các tập tin sơ khai
Trình trang trí from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]27 cho phép mô tả các hàm và phương thức hỗ trợ nhiều kiểu kết hợp đối số khác nhau. Mẫu này được sử dụng thường xuyên trong các loại và mô-đun dựng sẵn. Ví dụ, phương pháp def greeting(name: str) -> str: return 'Hello ' + name20 của loại def greeting(name: str) -> str: return 'Hello ' + name66 có thể được mô tả như sau from typing import TypeVar, Text AnyStr = TypeVar('AnyStr', Text, bytes) def concat(x: AnyStr, y: AnyStr) -> AnyStr: return x + y1 Mô tả này chính xác hơn so với khả năng sử dụng các liên kết (không thể diễn tả mối quan hệ giữa đối số và kiểu trả về) from typing import TypeVar, Text AnyStr = TypeVar('AnyStr', Text, bytes) def concat(x: AnyStr, y: AnyStr) -> AnyStr: return x + y2 Một ví dụ khác trong đó from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]27 có ích là loại hàm dựng sẵn from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]46, hàm này nhận số lượng đối số khác nhau tùy thuộc vào loại của hàm có thể gọi được from typing import TypeVar, Text AnyStr = TypeVar('AnyStr', Text, bytes) def concat(x: AnyStr, y: AnyStr) -> AnyStr: return x + y3 Lưu ý rằng chúng tôi cũng có thể dễ dàng thêm các mục để hỗ trợ from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]47 from typing import TypeVar, Text AnyStr = TypeVar('AnyStr', Text, bytes) def concat(x: AnyStr, y: AnyStr) -> AnyStr: return x + y4 Việc sử dụng trình trang trí from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]27 như được hiển thị ở trên phù hợp với các tệp sơ khai. Trong các mô-đun thông thường, một loạt các định nghĩa được trang trí bằng from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]27 phải được theo sau bởi chính xác một định nghĩa không được trang trí ____42_______27 (cho cùng một chức năng/phương pháp). Các định nghĩa được trang trí _ from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]27 chỉ dành cho lợi ích của trình kiểm tra loại, vì chúng sẽ bị ghi đè bởi định nghĩa không được trang trí ____42_______27, trong khi định nghĩa sau được sử dụng trong thời gian chạy nhưng trình kiểm tra loại sẽ bỏ qua. Trong thời gian chạy, việc gọi trực tiếp một hàm được trang trí from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]27 sẽ tăng from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]54. Đây là một ví dụ về tình trạng quá tải không sơ khai không thể dễ dàng biểu thị bằng cách sử dụng biến kết hợp hoặc biến loại from typing import TypeVar, Text AnyStr = TypeVar('AnyStr', Text, bytes) def concat(x: AnyStr, y: AnyStr) -> AnyStr: return x + y5 GHI CHÚ. Mặc dù có thể cung cấp triển khai nhiều công văn bằng cách sử dụng cú pháp này, nhưng việc triển khai nó sẽ yêu cầu sử dụng from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]55, điều này không được tán thành. Ngoài ra, việc thiết kế và triển khai một cơ chế điều phối nhiều lần hiệu quả là rất khó, đó là lý do tại sao những nỗ lực trước đó đã bị bỏ rơi để thay thế cho from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]56. (Xem PEP 443, đặc biệt là phần “Các phương pháp thay thế”. ) Trong tương lai, chúng tôi có thể đưa ra một thiết kế nhiều công văn thỏa đáng, nhưng chúng tôi không muốn một thiết kế như vậy bị hạn chế bởi quá tải cú pháp được xác định cho các gợi ý loại trong tệp sơ khai. Cũng có thể cả hai tính năng sẽ phát triển độc lập với nhau (vì quá tải trong trình kiểm tra loại có các trường hợp và yêu cầu sử dụng khác với nhiều lần gửi trong thời gian chạy – e. g. cái sau không có khả năng hỗ trợ các loại chung) Thường có thể sử dụng loại def greeting(name: str) -> str: return 'Hello ' + name61 bị ràng buộc thay vì sử dụng trình trang trí from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]27. Ví dụ: các định nghĩa của from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]59 và from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]60 trong tệp sơ khai này là tương đương from typing import TypeVar, Text AnyStr = TypeVar('AnyStr', Text, bytes) def concat(x: AnyStr, y: AnyStr) -> AnyStr: return x + y6 Một số chức năng, chẳng hạn như from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]61 hoặc from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]62 ở trên, không thể được biểu diễn chính xác bằng các biến loại. Tuy nhiên, không giống như from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]27, các biến kiểu cũng có thể được sử dụng bên ngoài các tệp sơ khai. Chúng tôi khuyên rằng chỉ nên sử dụng from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]27 trong trường hợp biến loại không đủ, do trạng thái chỉ sơ khai đặc biệt của nó Một sự khác biệt quan trọng khác giữa các biến loại như def greeting(name: str) -> str: return 'Hello ' + name72 và sử dụng from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]27 là biến trước đó cũng có thể được sử dụng để xác định các ràng buộc cho các tham số loại chung của lớp. Ví dụ: tham số kiểu của lớp chung from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]67 bị ràng buộc (chỉ from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]68, from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]69 và from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]70 là hợp lệ) from typing import TypeVar, Text AnyStr = TypeVar('AnyStr', Text, bytes) def concat(x: AnyStr, y: AnyStr) -> AnyStr: return x + y7 Hình thức lưu trữ và phân phối tệp sơ khai dễ dàng nhất là đặt chúng cùng với các mô-đun Python trong cùng một thư mục. Điều này làm cho chúng dễ dàng tìm thấy bởi cả người lập trình và công cụ. Tuy nhiên, vì các nhà bảo trì gói được tự do không thêm gợi ý loại vào các gói của họ, các sơ khai của bên thứ ba có thể cài đặt bởi from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]71 từ PyPI cũng được hỗ trợ. Trong trường hợp này chúng ta phải xem xét ba vấn đề. đặt tên, phiên bản, đường dẫn cài đặt PEP này không cung cấp đề xuất về sơ đồ đặt tên nên được sử dụng cho các gói tệp sơ khai của bên thứ ba. Khả năng khám phá hy vọng sẽ dựa trên mức độ phổ biến của gói, chẳng hạn như với các gói Django Sơ khai của bên thứ ba phải được phiên bản bằng phiên bản thấp nhất của gói nguồn tương thích. Thí dụ. FooPackage có phiên bản 1. 0, 1. 1, 1. 2, 1. 3, 2. 0, 2. 1, 2. 2. Có những thay đổi API trong phiên bản 1. 1, 2. 0 và 2. 2. Bộ duy trì gói tệp sơ khai được miễn phí phát hành sơ khai cho tất cả các phiên bản nhưng ít nhất 1. 0, 1. 1, 2. 0 và 2. Cần có 2 để kích hoạt loại người dùng cuối kiểm tra tất cả các phiên bản. Điều này là do người dùng biết rằng phiên bản sơ khai thấp hơn hoặc bằng gần nhất là tương thích. Trong ví dụ được cung cấp, đối với FooPackage 1. 3 người dùng sẽ chọn sơ khai phiên bản 1. 1 Lưu ý rằng nếu người dùng quyết định sử dụng gói nguồn có sẵn "mới nhất", thì việc sử dụng các tệp sơ khai "mới nhất" cũng sẽ hoạt động nếu chúng được cập nhật thường xuyên Gói sơ khai của bên thứ ba có thể sử dụng bất kỳ vị trí nào để lưu trữ sơ khai. Trình kiểm tra loại nên tìm kiếm chúng bằng PYTHONPATH. Thư mục dự phòng mặc định luôn được chọn là from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]72 (đối với một số PythonX. Y như được xác định bởi trình kiểm tra loại, không chỉ phiên bản đã cài đặt). Vì chỉ có thể có một gói được cài đặt cho một phiên bản Python nhất định cho mỗi môi trường, nên không có phiên bản bổ sung nào được thực hiện trong thư mục đó (giống như cài đặt thư mục trống bởi from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]71 trong gói trang web). Tác giả gói tệp sơ khai có thể sử dụng đoạn mã sau trong from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]74 from typing import TypeVar, Text AnyStr = TypeVar('AnyStr', Text, bytes) def concat(x: AnyStr, y: AnyStr) -> AnyStr: return x + y8 (CẬP NHẬT. Kể từ tháng 6 năm 2018, cách được đề xuất để phân phối gợi ý loại cho các gói của bên thứ ba đã thay đổi – ngoài cách đánh máy (xem phần tiếp theo), giờ đây còn có một tiêu chuẩn để phân phối gợi ý loại, PEP 561. It supports separately installable packages containing stubs, stub files included in the same distribution as the executable code of a package, and inline type hints, the latter two options enabled by including a file named from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]75 in the package. ) There is a shared repository where useful stubs are being collected. Policies regarding the stubs collected here will be decided separately and reported in the repo’s documentation. Note that stubs for a given package will not be included here if the package owners have specifically requested that they be omitted No syntax for listing explicitly raised exceptions is proposed. Currently the only known use case for this feature is documentational, in which case the recommendation is to put this information in a docstring To open the usage of static type checking to Python 3. 5 as well as older versions, a uniform namespace is required. For this purpose, a new module in the standard library is introduced called def greeting(name: str) -> str: return 'Hello ' + name14 It defines the fundamental building blocks for constructing types (e. g. def greeting(name: str) -> str: return 'Hello ' + name12), types representing generic variants of builtin collections (e. g. Url = str def retry(url: Url, retry_count: int) -> None: ...10), types representing generic collection ABCs (e. g. def greeting(name: str) -> str: return 'Hello ' + name17), and a small collection of convenience definitions Note that special type constructs, such as def greeting(name: str) -> str: return 'Hello ' + name12, def greeting(name: str) -> str: return 'Hello ' + name42, and type variables defined using def greeting(name: str) -> str: return 'Hello ' + name61 are only supported in the type annotation context, and def greeting(name: str) -> str: return 'Hello ' + name79 may only be used as a base class. All of these (except for unparameterized generics) will raise from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]85 if appear in from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]23 or from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) def inproduct(v: Iterable[Tuple[T, T]]) -> T: return sum(x*y for x, y in v) def dilate(v: Iterable[Tuple[T, T]], scale: T) -> Iterable[Tuple[T, T]]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Iterable[Tuple[float, float]]24 Fundamental building blocks
Generic variants of builtin collections
Ghi chú. def greeting(name: str) -> str: return 'Hello ' + name47, from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body05, Url = str def retry(url: Url, retry_count: int) -> None: ...10, Url = str def retry(url: Url, retry_count: int) -> None: ...12 và Url = str def retry(url: Url, retry_count: int) -> None: ...13 chủ yếu hữu ích cho việc chú thích các giá trị trả về. Đối với các đối số, hãy ưu tiên các loại tập hợp trừu tượng được xác định bên dưới, e. g. Url = str def retry(url: Url, retry_count: int) -> None: ...08, def greeting(name: str) -> str: return 'Hello ' + name17 hoặc from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body02 Các biến thể chung của ABC vùng chứa (và một số không phải vùng chứa)
Một số loại dùng một lần được xác định để kiểm tra các phương pháp đặc biệt đơn lẻ (tương tự như from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body21 hoặc from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body22)
định nghĩa tiện lợi
Các loại liên quan đến I/O
Các loại liên quan đến biểu thức chính quy và mô-đun from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body44
Một số công cụ có thể muốn hỗ trợ chú thích loại trong mã phải tương thích với Python 2. 7. Vì mục đích này, PEP này có phần mở rộng được đề xuất (nhưng không bắt buộc) trong đó các chú thích chức năng được đặt trong một nhận xét from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body48. Một bình luận như vậy phải được đặt ngay sau tiêu đề chức năng (trước chuỗi tài liệu). Một ví dụ. mã Python 3 sau đây from typing import TypeVar, Text AnyStr = TypeVar('AnyStr', Text, bytes) def concat(x: AnyStr, y: AnyStr) -> AnyStr: return x + y9 tương đương như sau def greeting(name: str) -> str: return 'Hello ' + name00 Lưu ý rằng đối với các phương thức, không cần loại cho from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body49 Đối với một phương thức không có đối số, nó sẽ trông như thế này def greeting(name: str) -> str: return 'Hello ' + name01 Đôi khi bạn muốn chỉ định kiểu trả về cho một hàm hoặc phương thức mà không (chưa) chỉ định các kiểu đối số. Để hỗ trợ điều này một cách rõ ràng, danh sách đối số có thể được thay thế bằng dấu chấm lửng. Thí dụ def greeting(name: str) -> str: return 'Hello ' + name02 Đôi khi bạn có một danh sách dài các tham số và việc chỉ định loại của chúng trong một nhận xét from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body48 sẽ rất khó xử. Để đạt được điều này, bạn có thể liệt kê một đối số trên mỗi dòng và thêm một nhận xét from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body48 trên mỗi dòng sau dấu phẩy liên quan của đối số, nếu có. Để chỉ định kiểu trả về, hãy sử dụng cú pháp dấu chấm lửng. Việc chỉ định kiểu trả về là không bắt buộc và không phải mọi đối số đều cần được cung cấp một kiểu. Một dòng có nhận xét from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body48 phải chứa chính xác một đối số. Nhận xét loại cho đối số cuối cùng (nếu có) phải đứng trước dấu ngoặc đơn đóng. Thí dụ def greeting(name: str) -> str: return 'Hello ' + name03 ghi chú
Khi kiểm tra Python 2. 7, người kiểm tra loại nên coi các loại Url = str def retry(url: Url, retry_count: int) -> None: ...64 và from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body60 là tương đương. Đối với các tham số được nhập là from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body61, các đối số thuộc loại def greeting(name: str) -> str: return 'Hello ' + name37 cũng như from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body32 phải được chấp nhận Trong quá trình thảo luận về các dự thảo trước đó của PEP này, nhiều ý kiến phản đối đã được đưa ra và các giải pháp thay thế đã được đề xuất. Chúng tôi thảo luận về một số trong số này ở đây và giải thích lý do tại sao chúng tôi từ chối chúng Một số phản đối chính đã được đưa ra Hầu hết mọi người đều quen thuộc với việc sử dụng dấu ngoặc nhọn (e. g. from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body64) bằng các ngôn ngữ như C++, Java, C# và Swift để thể hiện tham số hóa của các loại chung. Vấn đề với những thứ này là chúng thực sự khó phân tích cú pháp, đặc biệt đối với một trình phân tích cú pháp đơn giản như Python. Trong hầu hết các ngôn ngữ, sự mơ hồ thường được xử lý bằng cách chỉ cho phép các dấu ngoặc nhọn ở các vị trí cú pháp cụ thể, trong đó các biểu thức chung không được phép. (Và cũng bằng cách sử dụng các kỹ thuật phân tích cú pháp rất mạnh có thể quay lui một đoạn mã tùy ý. ) Nhưng trong Python, chúng ta muốn các biểu thức kiểu (về mặt cú pháp) giống với các biểu thức khác, để chúng ta có thể sử dụng e. g. gán biến để tạo bí danh kiểu. Hãy xem xét biểu thức loại đơn giản này def greeting(name: str) -> str: return 'Hello ' + name06 Từ quan điểm của trình phân tích cú pháp Python, biểu thức bắt đầu bằng bốn mã thông báo giống nhau (NAME, LESS, NAME, GREATER) dưới dạng so sánh theo chuỗi def greeting(name: str) -> str: return 'Hello ' + name07 Chúng tôi thậm chí có thể tạo một ví dụ có thể được phân tích cú pháp theo cả hai cách def greeting(name: str) -> str: return 'Hello ' + name08 Giả sử chúng ta có dấu ngoặc nhọn trong ngôn ngữ, điều này có thể được hiểu là một trong hai điều sau def greeting(name: str) -> str: return 'Hello ' + name09 Chắc chắn có thể đưa ra một quy tắc để phân biệt những trường hợp như vậy, nhưng đối với hầu hết người dùng, các quy tắc sẽ cảm thấy tùy tiện và phức tạp. Nó cũng sẽ yêu cầu chúng tôi thay đổi đáng kể trình phân tích cú pháp CPython (và mọi trình phân tích cú pháp khác cho Python). Cần lưu ý rằng trình phân tích cú pháp hiện tại của Python cố tình "câm" - một ngữ pháp đơn giản sẽ dễ dàng hơn cho người dùng suy luận về Vì tất cả những lý do này, dấu ngoặc vuông (e. g. from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body65) là (và từ lâu đã là) cú pháp ưa thích cho các tham số kiểu chung. Chúng có thể được triển khai bằng cách xác định phương thức def greeting(name: str) -> str: return 'Hello ' + name20 trên siêu dữ liệu và không yêu cầu cú pháp mới nào cả. Tùy chọn này hoạt động trong tất cả các phiên bản Python gần đây (bắt đầu với Python 2. 2). Python không đơn độc trong lựa chọn cú pháp này – các lớp chung trong Scala cũng sử dụng dấu ngoặc vuông Một dòng lập luận chỉ ra rằng PEP 3107 hỗ trợ rõ ràng việc sử dụng các biểu thức tùy ý trong chú thích hàm. Đề xuất mới sau đó được coi là không tương thích với đặc điểm kỹ thuật của PEP 3107 Phản hồi của chúng tôi về điều này là, trước hết, đề xuất hiện tại không đưa ra bất kỳ sự không tương thích trực tiếp nào, vì vậy các chương trình sử dụng chú thích trong Python 3. 4 sẽ vẫn hoạt động chính xác và không ảnh hưởng đến Python 3. 5 Chúng tôi hy vọng rằng các gợi ý kiểu cuối cùng sẽ trở thành mục đích sử dụng duy nhất cho các chú thích, nhưng điều này sẽ cần thảo luận thêm và một khoảng thời gian không dùng nữa sau lần triển khai đầu tiên của mô-đun gõ với Python 3. 5. PEP hiện tại sẽ có trạng thái tạm thời (xem PEP 411) cho đến Python 3. 6 được phát hành. Sơ đồ có thể hình dung nhanh nhất sẽ giới thiệu sự phản đối thầm lặng của các chú thích gợi ý không phải kiểu trong 3. 6, ngừng sử dụng hoàn toàn trong 3. 7 và khai báo gợi ý loại là cách sử dụng chú thích duy nhất được phép trong Python 3. 8. Điều này sẽ giúp tác giả của các gói sử dụng chú thích có nhiều thời gian để nghĩ ra cách tiếp cận khác, ngay cả khi gợi ý loại trở thành thành công chỉ sau một đêm (CẬP NHẬT. Kể từ mùa thu năm 2017, lịch trình kết thúc trạng thái tạm thời cho PEP này và cho mô-đun from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]79 đã thay đổi, và do đó, lịch trình ngừng sử dụng chú thích khác cũng vậy. Để biết lịch trình cập nhật, xem PEP 563. ) Một kết quả khác có thể xảy ra là các gợi ý loại cuối cùng sẽ trở thành ý nghĩa mặc định cho các chú thích, nhưng sẽ luôn có một tùy chọn để tắt chúng. Với mục đích này, đề xuất hiện tại xác định một trình trang trí def greeting(name: str) -> str: return 'Hello ' + name23 vô hiệu hóa việc diễn giải mặc định các chú thích dưới dạng gợi ý kiểu trong một lớp hoặc hàm đã cho. Nó cũng định nghĩa một meta-decorator from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]93 có thể được sử dụng để trang trí một decorator (. ), khiến các chú thích trong bất kỳ chức năng hoặc lớp nào được trang trí bằng cái sau sẽ bị trình kiểm tra loại bỏ qua Ngoài ra còn có from typing import TypeVar, Iterable, Tuple T = TypeVar('T', int, float, complex) Vector = Iterable[Tuple[T, T]] def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vector[T], scale: T) -> Vector[T]: return ((x * scale, y * scale) for x, y in v) vec = [] # type: Vector[float]91 nhận xét và trình kiểm tra tĩnh phải hỗ trợ các tùy chọn cấu hình để tắt kiểm tra loại trong các gói đã chọn Bất chấp tất cả các tùy chọn này, các đề xuất đã được lưu hành để cho phép các gợi ý loại và các hình thức chú thích khác cùng tồn tại cho các đối số riêng lẻ. Một đề xuất gợi ý rằng nếu một chú thích cho một đối số nhất định là một từ điển theo nghĩa đen, thì mỗi khóa đại diện cho một dạng chú thích khác nhau và khóa from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body71 sẽ được sử dụng cho các gợi ý loại. Vấn đề với ý tưởng này và các biến thể của nó là ký hiệu trở nên rất “ồn ào” và khó đọc. Ngoài ra, trong hầu hết các trường hợp khi thư viện hiện có sử dụng chú thích, sẽ không cần kết hợp chúng với gợi ý loại. Vì vậy, cách tiếp cận đơn giản hơn để vô hiệu hóa có chọn lọc các gợi ý loại có vẻ đủ Đề xuất hiện tại được thừa nhận là không tối ưu khi các gợi ý loại phải chứa các tham chiếu chuyển tiếp. Python yêu cầu tất cả các tên được xác định theo thời gian chúng được sử dụng. Ngoài việc nhập khẩu vòng tròn, đây hiếm khi là một vấn đề. “use” ở đây có nghĩa là “tra cứu trong thời gian chạy” và với hầu hết các tham chiếu “chuyển tiếp”, không có vấn đề gì trong việc đảm bảo rằng một tên được xác định trước khi hàm sử dụng nó được gọi Vấn đề với các gợi ý loại là các chú thích (theo PEP 3107 và tương tự như các giá trị mặc định) được đánh giá tại thời điểm một hàm được xác định và do đó, bất kỳ tên nào được sử dụng trong một chú thích đều phải được xác định khi hàm đang được xác định. Một tình huống phổ biến là một định nghĩa lớp có các phương thức cần tham chiếu chính lớp đó trong các chú thích của chúng. (Tổng quát hơn, nó cũng có thể xảy ra với các lớp đệ quy lẫn nhau. ) Điều này là tự nhiên đối với các loại container, ví dụ def greeting(name: str) -> str: return 'Hello ' + name10 Như đã viết, điều này sẽ không hoạt động, do tính đặc thù của Python mà các tên lớp được xác định sau khi toàn bộ nội dung của lớp đã được thực thi. Giải pháp của chúng tôi, không đặc biệt thanh lịch, nhưng đã hoàn thành công việc, là cho phép sử dụng các chuỗi ký tự trong chú thích. Mặc dù vậy, hầu hết thời gian bạn sẽ không phải sử dụng điều này – hầu hết việc sử dụng các gợi ý loại được dự kiến sẽ tham chiếu các loại dựng sẵn hoặc các loại được xác định trong các mô-đun khác Một đề xuất ngược lại sẽ thay đổi ngữ nghĩa của các gợi ý loại để chúng hoàn toàn không được đánh giá trong thời gian chạy (xét cho cùng, việc kiểm tra loại diễn ra ngoại tuyến, vậy tại sao các gợi ý loại lại cần được đánh giá trong thời gian chạy). Tất nhiên, điều này sẽ dẫn đến khả năng tương thích ngược, vì trình thông dịch Python không thực sự biết liệu một chú thích cụ thể có phải là một gợi ý kiểu hay không. A compromise is possible where a from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body72 import could enable turning all annotations in a given module into string literals, as follows def greeting(name: str) -> str: return 'Hello ' + name11 Một tuyên bố nhập khẩu from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body72 như vậy có thể được đề xuất trong một PEP riêng biệt. (CẬP NHẬT. Tuyên bố nhập khẩu from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body72 đó và hậu quả của nó được thảo luận trong PEP 563. ) Một số tâm hồn sáng tạo đã cố gắng phát minh ra giải pháp cho vấn đề này. Ví dụ: người ta đề xuất sử dụng dấu hai chấm (_______44_______75) cho gợi ý loại, giải quyết hai vấn đề cùng một lúc. phân biệt giữa các gợi ý loại và các chú thích khác, đồng thời thay đổi ngữ nghĩa để ngăn chặn việc đánh giá thời gian chạy. Có một số điều sai với ý tưởng này, tuy nhiên
Một vài hình thức khác của cú pháp thay thế đã được đề xuất, e. g. việc giới thiệu một từ khóa from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body78 và mệnh đề from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body79 lấy cảm hứng từ Rắn hổ mang. Nhưng tất cả đều có chung một vấn đề với dấu hai chấm. chúng sẽ không hoạt động đối với các phiên bản Python 3 cũ hơn. Điều tương tự cũng áp dụng cho lần nhập from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # Body72 mới Các ý tưởng đưa ra bao gồm
Nó cũng được đề xuất là chỉ cần đợi một bản phát hành khác. Nhưng vấn đề đó sẽ giải quyết vấn đề gì? Bản nháp trực tiếp cho PEP này có trên GitHub. Ngoài ra còn có một trình theo dõi vấn đề, nơi diễn ra nhiều cuộc thảo luận kỹ thuật Bản nháp trên GitHub được cập nhật thường xuyên theo từng bước nhỏ. Repo PEPS chính thức (thường) chỉ được cập nhật khi bản nháp mới được đăng lên python-dev Tài liệu này không thể hoàn thành nếu không có những ý kiến đóng góp, khuyến khích và lời khuyên có giá trị từ Jim Baker, Jeremy Siek, Michael Matson Vitousek, Andrey Vlasovskikh, Radomir Dopieralski, Peter Ludemann, và Đại biểu BDFL, Mark Shannon Ảnh hưởng bao gồm các ngôn ngữ, thư viện và khuôn khổ hiện có được đề cập trong PEP 482. Rất cám ơn những người tạo ra chúng, theo thứ tự bảng chữ cái. Stefan Behnel, William Edwards, Greg Ewing, Larry Hastings, Anders Hejlsberg, Alok Menghrajani, Travis E. Oliphant, Joe Pamer, Raoul-Gabriel Urma, and Julien Verlaguet Không liên kết có nghĩa là gì trong Python?Một ký hiệu chưa được gán giá trị khi gán hoặc trong lệnh gọi hàm được gọi là "không liên kết. ”
Why is variable unbound Python?Lỗi cục bộ không liên kết xảy ra khi một biến cục bộ được tham chiếu trước khi nó được gán . Các biến trong Python chỉ được chỉ định bên trong một hàm toàn cục theo mặc định. Nếu một giá trị được gán cho một biến trong thân hàm, trừ khi nó được xác định rõ ràng là toàn cục, thì nó được coi là cục bộ.
Sự khác biệt giữa các phương thức ràng buộc và không ràng buộc là gì?Phương thức không liên kết về cơ bản là một hàm với một số phần bổ sung. 'Phương thức ràng buộc' được gọi như vậy vì đối số đầu tiên (tức là self ) đã được đặt thành ; . fred(10) (điều này thực sự cần thiết dựa trên cách thức hoạt động của CPython).
What is an unbound function?Bây giờ, hàm số không bị chặn trên hoặc dưới bởi một giới hạn hữu hạn được gọi là hàm không bị chặn. Ví dụ. - x là một hàm không bị chặn vì nó suy rộng từ −∞ đến ∞. |