Không có hay không có trong python?

Lần này chúng ta hãy nói về [trong]None nổi tiếng trong Python, các hình dạng và kiểu sử dụng khác nhau của nó. Hãy để chúng tôi cố gắng tìm cách đi xung quanh mà không có nó

Trong quá trình làm việc chuyên nghiệp của mình, tôi đã dành vài năm trong thế giới lập trình chức năng. Bạn biết đấy, điều này được đánh máy nghiêm ngặt. Sau đó, khi tôi quay lại Python, tôi nhận thấy rằng họ đã giới thiệu các chú thích kiểu trong thời gian chờ đợi, điều đó thật tuyệt phải không?

Nghĩa đen bắt đầu từ Không có gì, tôi tìm thấy Không. Và đó là nội dung của câu chuyện này ;-]

Vì vậy, đây là chức năng Python yêu thích của tôi

def magic_function[]:
# mysterious things happening here
print["Pure magic!"]

Thoạt nhìn, có vẻ như một hàm không nhận đầu vào nào không trả về gì, vì nó không có câu lệnh trả về. Bây giờ hãy thử một cái gì đó kỳ lạ

>>> magic = magic_function[]
Pure magic!

Không có gì ngạc nhiên khi hàm in ra thiết bị xuất chuẩn, nhưng điều thú vị là chúng ta gán kết quả của hàm magic_function[] cho biến magic. Làm thế nào mà có thể?

>>> magic.__class__
>>> magic is None
True
>>> None.__class__

Đương nhiên, Pythonista hiểu biết biết rằng mọi [. ] không có câu lệnh trả về rõ ràng sẽ hoàn toàn trả về Không [trừ khi nó đưa ra một ngoại lệ] — và đây là những gì chúng ta gán cho 'ma thuật'. Vì vậy, phép thuật trở thành một biến thuộc loại 'lớp Không có Loại' - phép thuật giống hệt với Không có

Nếu một cái gì đó có một danh tính, ngay cả khi nó được gọi là Không, nó không thể là không có gì, phải không?

Ok, Không có gì là một phiên bản "thực" của loại "thực". Có vẻ như đây là bằng chứng đầu tiên cho thấy “Không có gì là KHÔNG có gì”, đúng không?

Nhờ các chú thích loại, chúng tôi có thể làm cho chữ ký chức năng của mình hấp dẫn hơn

def magic_function[] -> None:
....

Người dùng của hàm_ma_thuật[] ngay lập tức biết rằng cô ấy không thể mong đợi hàm trả về bất kỳ thứ gì có ý nghĩa. Có mùi như thế này "void" thingy trong C cũ tốt

void magic_function[void] {
....
}

Những cấu trúc như thế này không xứng đáng được gọi là “chức năng”, đó là lý do tại sao chúng được đặt tên là “thủ tục”

Thật không may, đó không phải là toàn bộ sự thật, vì Không có gì trong Python dường như là một giá trị hợp lệ cho mọi loại. Chúng ta có thể dễ dàng chứng minh điều đó bằng cách viết lại hàm ma thuật của mình để chỉ trả về một số phép thuật vào ngày đầu tiên của tháng

from datetime import datetime
from typing import Optional
def maybe_magic_function[] -> Optional[str]:
return "magic" if datetime.now[].day == 1 else None

Ở đây chúng tôi xác định rằng hàm tùy chọn trả về chuỗi. Nhưng nó cũng được phép trả về Không có. Như một ghi chú nhanh, trước khi gõ. Tùy chọn đã được giới thiệu, bạn phải viết

from typing import Uniondef maybe_magic_function[] -> Union[str, None]:
....

Bắt đầu với phiên bản 3. 10 bạn thậm chí có thể viết ngắn gọn hơn

def maybe_magic_function[] -> str | None:
....

Cả ba biến thể đều tương đương nhau và mỗi biến thể sẽ khiến những người kiểm tra kiểu tĩnh như mypy vô cùng hài lòng. Cá nhân, tôi có xu hướng gặp vấn đề với những đặc thù như vậy. Hãy để tôi giải thích tại sao

Không có giá trị trả về thường được sử dụng để đại diện cho những thứ khác nhau

  1. Các hàm trả về Không có hoặc một giá trị cụ thể -> được biểu thị bằng Tùy chọn [Bất kỳ]
  2. Các hàm trả về Không để biểu thị lỗi -> được biểu thị bằng Tùy chọn [Bất kỳ]
  3. Các hàm trả về Không để biểu thị không có giá trị trả về -> được biểu thị bằng Không

Trong bất kỳ trường hợp nào trong số này, việc trả lại Không có gì khác hơn là một quy ước. Không thể lấy được bất kỳ ý định rõ ràng nào từ Không có. Do đó, bạn thường thấy vô số dòng thác “nếu có gì đó là Không” [một. k. a. kim tự tháp diệt vong]. Chỉ cần nghĩ xem bạn đã viết bao nhiêu dòng mã trong sự nghiệp của mình chỉ để kiểm tra các Quy ước không có này [xem thêm sai lầm tỷ đô la]

Và có một sự tinh tế khác với Không. Chúng tôi đã phát hiện ra rằng Không có gì là một đối tượng có danh tính và thậm chí là một loại [lớp Không có Loại]. Bây giờ, khi chú thích các biến và hàm, chúng ta đang sử dụng các kiểu, phải không?

Giống

________số 8

'str' là một loại và 'int' là một loại nhưng Không có gì là một đối tượng của loại 'lớp Không có Loại'. Có phải chúng ta đang trộn lẫn các loại và đối tượng?

Thật thú vị, chúng tôi không được phép viết

>>> def maybe_magic_function[i: int] -> Union[str, NoneType]:
...
Traceback [most recent call last]:
File "", line 1, in
NameError: name 'NoneType' is not defined
>>> type[None]
>>> type[int]

We cannot use NoneType, as Python says: “name ‘NoneType’ is not defined”. If NoneType is undefined but calling type[None] results in , then what does it tell us about None? Does it mean that None is an object of an undefined type? How can something be an object if its type is undefined? Never ending questions…

Bạn thấy đấy, có rất nhiều huyền thoại xung quanh Không có gì… Hãy tìm hiểu sâu hơn. -]

Dù sao đi nữa, để không phải loay hoay với tất cả những đặc điểm đó, làm cách nào tôi có thể tạo các giá trị trả về thể hiện rõ ràng các khái niệm như sự vắng mặt [i. e. Không có gì] hoặc thất bại [các loại khác nhau]?

Các loại để giải cứu

Như chúng ta đã biết, hệ thống kiểu của Python là động và được triển khai theo khái niệm kiểu vịt [các phương thức mà một đối tượng có quan trọng hơn kiểu cụ thể]. Tuy nhiên, mọi đối tượng trong Python đều có một loại, được trình thông dịch tự động suy ra. Với việc giới thiệu các chú thích kiểu và trình kiểm tra kiểu tĩnh, việc thêm thông tin kiểu mang lại cho chúng ta ấn tượng [ảo] về việc xử lý một ngôn ngữ kiểu tĩnh, ít nhất là trong IDE

Vì vậy, làm thế nào chúng ta có thể sử dụng tất cả những điều đó để lợi thế của chúng tôi?

đại diện cho sự vắng mặt

Chúng tôi có thể biểu thị sự vắng mặt bằng cách sử dụng một loại chuyên dụng có tên là Có thể có hai loại phụ. Chỉ bao bọc một giá trị cụ thể trong khi Không có gì đại diện cho sự vắng mặt

>>> magic = magic_function[]
Pure magic!
0

Không phải ngẫu nhiên mà tôi gọi kiểu đó là Có thể. Phải thừa nhận rằng, đây có lẽ là cách triển khai ngây thơ và không đầy đủ nhất của Maybe monad nổi tiếng từ trước đến nay. -]. Bây giờ đừng quan tâm đến thuật ngữ "đơn nguyên", chúng ta ở đây để tìm hiểu về khái niệm đại diện cho sự vắng mặt. -]

Bằng cách chú thích hàm magic_function[] của chúng ta với kiểu kết quả Có thể, sẽ không còn chỗ cho sự không chắc chắn. Loại kết quả là Chỉ hoặc Không có gì, dừng hoàn toàn

Sử dụng khớp mẫu cấu trúc [Python ≥ 3. 10] bạn có thể dễ dàng mở gói giá trị được đóng gói từ Chỉ và xử lý trường hợp Không có gì tương ứng

>>> magic = magic_function[]
Pure magic!
1

Ngoài ra, hãy sử dụng phương thức get_or_else[] trong Python < 3. 10

>>> magic = magic_function[]
Pure magic!
2

Sẽ còn nhiều điều nữa để nói về Chân lý Có thể nhưng điều đó vượt xa phạm vi của bài viết này. Đối với những người tò mò, hãy để tôi tham khảo , đi kèm với triển khai hoàn thiện và được chú thích kiểu đầy đủ

Đại diện cho "không xác định"

Kịch bản thú vị tiếp theo là các hàm theo nghĩa toán học chỉ được xác định một phần theo tập hợp đầu vào của chúng. Chúng ta đều biết những hàm như chia cho 0, căn bậc hai của số âm, v.v.

Hãy nghĩ về một hàm tính tên ngày của một ngày cụ thể

>>> magic = magic_function[]
Pure magic!
3

Trong các ngôn ngữ lập trình, chúng ta thường gặp phải các trường hợp ngoại lệ, vì không thể biểu thị “không xác định” theo một cách có ý nghĩa, ít nhất là trong Python thì không có gì

Chúng ta cũng có thể sử dụng Maybe ở đây. Một phép tính trả về một giá trị cụ thể, nếu không, chúng ta có thể coi nó là không xác định. Là một tác dụng phụ có lợi, chúng tôi đang loại bỏ những ngoại lệ thời gian chạy khó chịu đó

>>> magic = magic_function[]
Pure magic!
4

Chúng tôi thậm chí có thể tự viết cho mình một công cụ trang trí tiện dụng để chúng tôi không phải làm ô nhiễm các chức năng của mình bằng mã xử lý lỗi

>>> magic = magic_function[]
Pure magic!
5

Với điều đó trong tay, chúng ta có thể trang trí các hàm một cách độc đáo khi chúng ta đã biết trước rằng chúng sẽ không được xác định đối với các giá trị đầu vào nhất định

>>> magic = magic_function[]
Pure magic!
6

Đại diện cho sự thất bại

Một lần nữa, chúng tôi sử dụng một hệ thống phân cấp lớp nhỏ để thể hiện thành công và thất bại và chúng tôi gọi đó là Kết quả

>>> magic = magic_function[]
Pure magic!
7

Kết quả hiện đang gói gọn một ngoại lệ cho trường hợp lỗi. Cảm giác đó như thế nào? . Lần này, đối tượng Thất bại cũng chứa thông tin bổ sung, bản thân nó là một đối tượng ngoại lệ

Điều này có nghĩa là việc giải nén Thất bại vẫn dẫn đến một ngoại lệ

>>> magic = magic_function[]
Pure magic!
8

Chúng ta có thể tránh điều đó bằng cách sử dụng get_or_else[]…

>>> magic = magic_function[]
Pure magic!
9

Hoặc khớp mẫu một lần nữa…

>>> magic.__class__
>>> magic is None
True
>>> None.__class__
0

Một lần nữa, hãy xem gói trả về có triển khai Kết quả tốt hơn nhiều

BTW. Có một loại khác ngoài đó được gọi là Hoặc, có hai loại phụ thường được gọi là Trái và Phải. Nó rất giống với Kết quả với sự khác biệt là Right đại diện cho con đường hạnh phúc [như Thành công] của một phép tính trong khi Left dành cho con đường không hài lòng - đây không nhất thiết phải là trường hợp ngoại lệ

Gì bây giờ?

Hãy để tôi tóm tắt

Có thể được sử dụng để chỉ ra rằng một hàm có trả về một giá trị cụ thể hay không. Tương tự, hãy nghĩ về các hàm toán học không xác định đối với các giá trị đầu vào nhất định. [BTW. Trong Scala, Maybe được gọi là Option với Some[value] ore Không có[. ] dưới dạng các loại phụ cụ thể]

Kết quả thường được sử dụng để "cụ thể hóa" các ngoại lệ và xử lý chúng theo một cách xác định. Ngoại lệ là tác dụng phụ tàn phá, tồi tệ nhất từng được phát minh. Nếu không được xử lý đúng cách, chúng sẽ mang đến cho bạn sự hỗn loạn tột độ. Vì vậy, đi và tránh chúng

Một trong hai được sử dụng để biểu thị các hoạt động có thể có hai đầu ra khả thi, một đầu ra “vui vẻ” hơn một chút so với đầu ra kia. Bạn cũng có thể nghĩ Hoặc là một tổng quát của Kết quả

Sự kết luận

câu hỏi cuối cùng. Trong tất cả các ví dụ được trình bày, bạn có phát hiện ra một lần xuất hiện duy nhất của Không? . Vì vậy, vâng, có cuộc sống mà không có ai trong Python

Sử dụng các loại cụ thể để thể hiện các kết quả tính toán cụ thể, chúng tôi có thể loại bỏ Không và thậm chí chúng tôi có thể làm cho các ngoại lệ trở nên rõ ràng, để luồng điều khiển tự nhiên của chương trình vẫn còn nguyên vẹn

không phải là VS. = Python Không có?

Bằng Python . = được định nghĩa là không bằng toán tử . Nó trả về True nếu toán hạng ở hai bên không bằng nhau và trả về False nếu chúng bằng nhau. Trong khi đó, toán tử không kiểm tra xem id[] của hai đối tượng có giống nhau hay không.

Không phải là Không có điều kiện trong Python?

Sử dụng toán tử is not để kiểm tra xem một biến có phải là Không có trong Python hay không , e. g. nếu my_var không phải là Không có. . Toán tử is not trả về True nếu các giá trị ở bên trái và bên phải không trỏ đến cùng một đối tượng [cùng một vị trí trong bộ nhớ].

== là gì và. = bằng Python?

So sánh đẳng thức với Python == và. = . Sử dụng toán tử đẳng thức == và. = nếu bạn muốn kiểm tra xem hai đối tượng có cùng giá trị hay không, bất kể chúng được lưu trữ ở đâu trong bộ nhớ.

Không có int trong Python?

int[None] đưa ra một ngoại lệ vì None không thể được chuyển thành int . Câu trả lời cho câu hỏi của bạn là nó không thể được thực hiện. Bạn có thể thay thế một cái gì đó, chẳng hạn như 0, hoặc 2771, hoặc một con voi màu hồng, nhưng bất kể bạn thay thế gì, bạn vẫn không thể chuyển đổi Không thành số nguyên.

Chủ Đề