Có rất nhiều biến thể về chủ đề này đến nỗi chúng tôi sẽ thật ngớ ngẩn khi nhấn mạnh vào Một cách viết đúng. Ví dụ: trong mã của riêng tôi, biến thể phổ biến nhất là
if item is None:
item = default[]
process_item[item]
Mặc dù có nhiều cách hay để giải quyết vấn đề này, nhưng việc viết một câu phủ định kép
if not [item is not None]:
không bao giờ là một trong số họ. Điều đó sẽ không thể diễn tả được. Không có câu hỏi hóc búa nào ở đây, đó là một paddlin'
Quay trở lại đề xuất của bạn, tôi e rằng bạn dường như đang hiểu sai về Không. Mặc dù đúng là Không có gì hiện là một từ khóa, nhưng nó cũng là một đối tượng, giống như mọi giá trị khác trong Python
is None
và is not None
không phải là các dạng cú pháp đặc biệt, mà là các toán tử cũ đơn giản với một toán hạng tình cờ là đối tượng Không có
Và do đó, nó sẽ dành cho is Any
được đề xuất của bạn, điều này sẽ phải kiểm tra xem liệu biểu thức bên trái có đánh giá được đối tượng Any
thực tế hay không
Bây giờ, tất nhiên, theo giả thuyết, chúng ta có thể tạo một dạng cú pháp đặc biệt is Any
biên dịch thành is not None
, nhưng loại trường hợp đặc biệt đó trong ngôn ngữ thậm chí còn khó nói hơn cả phủ định kép
Không có "có thể giới thiệu tải nhận thức" ở đây. Nó chắc chắn sẽ giới thiệu tải nhận thức
Nó sẽ làm phức tạp mô hình thực thi của Python. Thay vì
if not [item is not None]:
2 là một toán tử đơn giản luôn kiểm tra xem hai toán hạng có phải là cùng một đối tượng hay không, đôi khi nó sẽ đại diện cho phép kiểm tra ngược lại ["chúng có phải là cùng một đối tượng không?"] với toán hạng thứ hai không được nêuTệ hơn, nó sẽ phá vỡ khả năng tương thích ngược. "Bất kỳ" hiện là một tên thông thường miễn phí cho mọi người sử dụng. Có một đối tượng rất quan trọng trong stdlib có tên đó
from typing import Any
Với đề xuất này, bạn sẽ không thể kiểm tra xem một đối tượng có phải là Bất kỳ đối tượng nào bằng cách sử dụng
if not [item is not None]:
2 hay không, bởi vì is Any
sẽ có ý nghĩa ma thuật đặc biệtĐược rồi, có lẽ không phải là không thể. Có lẽ bạn có thể viết
Any is myobject
thay vào đó, nhưng điều đó dẫn đến kết quả tồi tệ hơn là bây giờ
if not [item is not None]:
2 không còn đối xứng nữaa is b
b is a
sẽ không còn có cùng ý nghĩa. [Có rất nhiều phép toán không đối xứng trong Python và toán học, chẳng hạn như phép trừ, phép chia, nhưng để
if not [item is not None]:
2 không đối xứng thì thật kỳ lạ. ]Về cơ bản, đây sẽ là một từ “Wot?” khó hiểu và kỳ lạ.
item is not None
item is Any
# doesn't actually test whether item is Any, but tests whether item is not None
Một điều cuối cùng… is not None
không nên được hiểu là liên quan đến
if not [item is not None]:
8. Toán tử là if not [item is not None]:
9 và toán hạng vẫn là Không có. if not [item is not None]:
8 sẽ cho kết quả là True Tôi hiểu rằng Optional[T]
thực sự chỉ là Union[T, None]
và sự tương tự với các tùy chọn trong Rust hoặc Swift là một sự tương tự hạn chế. Nhưng tôi muốn chỉ ra tại sao kiểu thu hẹp kiểu mà tôi và những người khác muốn lại khác với kiểu thu hẹp kiểu khác
Kỷ nguyên thất bại và vấn đề với Zero
Hãy xem xét một loại lỗi phổ biến mà tôi muốn gọi là “Thất bại kỷ nguyên”. Đây là nơi một số quy trình cố gắng đọc dấu thời gian Unix và không thành công. Thay vì xử lý lỗi đó, mã lỗi xử lý giá trị bằng 0. Nhưng dấu thời gian Unix bằng 0 là giây cuối cùng của năm 1969. Chúng tôi nhận được kết quả như
Sử dụng 0 để biểu thị trường hợp đặc biệt hoặc không có giá trị dẫn đến lỗi khi 0 cũng có thể là một giá trị nhất quán. Vì vậy, sẽ rất hữu ích khi có một cách để chỉ ra rằng không có giá trị cho một thứ gì đó. None
là hoàn hảo cho điều đó
Khi Không có không phải là một lỗi
Bây giờ trong ví dụ đó, việc không đọc được dấu thời gian gần như chắc chắn là một số lỗi cần được xử lý như một lỗi. Nhưng có những trường hợp không có giá trị [hay còn gọi là None
] không phải là lỗi
Giả sử bạn có một đối tượng cho một số loại trạng thái trò chơi hoặc mô phỏng được cập nhật sau mỗi vòng mô phỏng. Một số biến đối tượng sẽ phụ thuộc vào những thứ từ vòng trước. Một số thậm chí có thể phụ thuộc vào hai vòng trước. Do đó, những biến đó không thể được đặt thành bất kỳ thứ gì có ý nghĩa trong thời gian __init[]__
. Vì vậy, trong quá trình init, chúng tôi muốn đặt các biến đó thành Không có
Trong mỗi vòng của trò chơi hoặc mô phỏng của chúng tôi, sẽ có một số phương pháp được gọi là cần phải hành xử là những cách đặc biệt. Sẽ có một bài kiểm tra nếu một biến là None
. Trường hợp đó vẫn ổn và nó không được trợ giúp bằng cách có một thứ giống như TypeGuard nội tuyến
Nhưng sẽ có những chức năng khác giả định rằng các tham số mà nó được cung cấp không phải là Không có. Giả sử một xác suất được cập nhật, nhưng làm như vậy phụ thuộc vào các tham số tìm kiếm nhất định và kết quả từ vòng trước. Giả sử chúng ta có một cái gì đó như
def updated_prob[probability: float, search_effectiveness: float] -> float:
...
class SearchArea:
def __init__[initial_probability: float]:
self.p: float = initial_probability
self.search_effectiveness: Optional[float] = None
def conduct_search[self] -> None:
...
self.search_effectiveness = self.compute_a_lot_stuff[]
...
self.p = updated_prob[self.p, self.search_effectiveness]
...
Nếu updated_prob[]
là một hàm khá chung chung thực sự chỉ nhận các đối số float thì nó phải được khai báo với các gợi ý kiểu _____14_______0 cho các đối số của nó. Và trong khi chúng ta luôn có thể thêm một
if self.search_effectiveness is None:
raise Exception
trước khi gọi đến
if self.search_effectiveness is None:
raise Exception
1, giả sử chúng ta muốn gọi ____14_______1 trong cách hiểu danh sách hoặc trong một đối số của hàm nào đóCó thể nói những điều như
p = ...
probs_by_se = [updated_prob[p, se!] for se in effectiveness_list]
với
if self.search_effectiveness is None:
raise Exception
3 giúp việc viết mã rõ ràng và truyền đạt những gì chúng tôi muốn đến trình kiểm tra loại trở nên dễ dàng hơn nhiều[Ghi chú. Tất cả mã ở đây là thứ tôi đã nhập trực tiếp vào giao diện web để thảo luận. Nó có thể có nhiều lỗi cú pháp]