Tôi có thể sử dụng:
if A:
thay vì
if A is not None:
Cái sau có vẻ dài dòng. Có sự khác biệt?
Tôi có thể sử dụng:
if A:
thay vì
if A is not None:
Cái sau có vẻ dài dòng. Có sự khác biệt?
Câu trả lời:
Tuyên bố
if A:
sẽ gọi A.__nonzero__()(xem tài liệu tên phương thức đặc biệt ) và sử dụng giá trị trả về của hàm đó. Đây là tóm tắt:
object.__nonzero__(self)Được gọi để thực hiện kiểm tra giá trị thật và hoạt động tích hợp
bool(); nên trả vềFalsehoặcTrue, hoặc số nguyên tương đương của chúng0hoặc1. Khi phương thức này không được xác định,__len__()được gọi, nếu nó được xác định và đối tượng được coi là đúng nếu kết quả của nó là khác không. Nếu một lớp định nghĩa không phải__len__()cũng không__nonzero__(), tất cả các thể hiện của nó được coi là đúng.
Mặt khác,
if A is not None:
chỉ so sánh các tham chiếu Avới Noneđể xem liệu nó có giống nhau hay không.
if object(): passlà ~ 0,130 usec mỗi vòng, trong khi if object() is not None: passlà ~ 0,135 usec. Dù sao, bạn không nên sử dụng hiệu suất để lựa chọn giữa hai điều này, mà nên nhìn vào sự khác biệt trong cách chúng hoạt động, vì chúng không tương đương .
if A is not Nonedường như chậm hơn vì đó là so sánh và cần tải singleton dựng sẵn Nonenhư một bước trung gian để so sánh với A(hãy xem dis.dis()). Sửa lỗi cho tôi nếu tôi sai nhưng if A:dường như hiệu quả hơn, ngay khi bạn thực sự muốn kiểm tra giá trị thật và không phải Nonedanh tính.
python -m timeit -s"a=0" "if a: pass" "else: pass"nhanh hơn python -m timeit -s"a=0" "if a is None: pass" "else: pass"nhưng python -m timeit -s"a=1" "if a: pass" "else: pass"chậm hơn. Có thể phụ thuộc vào nền tảng, xem bạn có nhận được kết quả tương tự không
is Nonethử nghiệm thực sự là chậm nhất đối với tôi. Trong pypy tất cả đều đo chính xác như nhau :)
Như được viết trong PEP8 :
Việc so sánh với những người độc thân như Không nên luôn luôn được thực hiện với 'là' hoặc 'không', không bao giờ là các toán tử đẳng thức .
Ngoài ra, hãy cẩn thận khi viết "if x" khi bạn thực sự có nghĩa là "nếu x không phải là Không" - ví dụ: khi kiểm tra xem một biến hoặc đối số mặc định là Không được đặt thành một giá trị khác. Giá trị khác có thể có một loại (chẳng hạn như một thùng chứa) có thể sai trong bối cảnh boolean!
None, mà chỉ kiểm tra giá trị thật. Trong trường hợp này, if A:có vẻ hiệu quả hơn (thực hiện dis.dis(), có thêm các bước tải nội dung Nonevà so sánh if A is not None:, trong khi chỉ có một jump_iftrong trường hợp khác).
if x: #x is treated True except for all empty data types [],{},(),'',0 False, and None
vì vậy nó không giống như
if x is not None # which works only on None
Rất nhiều hàm trả về Không nếu không có kết quả phù hợp. Ví dụ: .first()phương thức của truy vấn SQLAlchemy trả về Không nếu không có hàng nào trong kết quả. Giả sử bạn đang chọn một giá trị có thể trả về 0 và cần biết liệu đó thực sự là 0 hay liệu truy vấn không có kết quả nào cả.
Một thành ngữ phổ biến là cung cấp cho đối số tùy chọn của hàm hoặc phương thức giá trị mặc định là Không, và sau đó kiểm tra giá trị đó là Không để xem nó có được chỉ định hay không. Ví dụ:
def spam(eggs=None):
if eggs is None:
eggs = retrievefromconfigfile()
so sánh với:
def spam(eggs=None):
if not eggs:
eggs = retrievefromconfigfile()
Sau này, điều gì xảy ra nếu bạn gọi spam(0)hoặc spam([])? Hàm sẽ (không chính xác) phát hiện ra rằng bạn đã không chuyển vào một giá trị cho eggsvà sẽ tính toán một giá trị mặc định cho bạn. Đó có lẽ không phải là những gì bạn muốn.
Hoặc tưởng tượng một phương pháp như "trả về danh sách các giao dịch cho một tài khoản nhất định". Nếu tài khoản không tồn tại, nó có thể trả về Không có. Điều này khác với việc trả về một danh sách trống (có nghĩa là "tài khoản này tồn tại nhưng chưa được ghi lại giao dịch).
Cuối cùng, trở lại công cụ cơ sở dữ liệu. Có một sự khác biệt lớn giữa NULL và một chuỗi rỗng. Một chuỗi rỗng thường nói "có một giá trị ở đây và giá trị đó hoàn toàn không có gì". NULL nói "giá trị này chưa được nhập."
Trong mỗi trường hợp đó, bạn muốn sử dụng if A is None. Bạn đang kiểm tra một giá trị cụ thể - Không - không chỉ "bất kỳ giá trị nào xảy ra để chuyển thành Sai".
Họ làm những việc rất khác nhau .
Kiểm tra dưới đây nếu A có bất cứ điều gì ngoại trừ các giá trị False, [], None, ''và 0. Nó kiểm tra giá trị của A.
if A:
Dưới đây kiểm tra nếu A là một đối tượng khác với Không. Nó kiểm tra và so sánh tham chiếu (địa chỉ bộ nhớ) của A và Không có.
if A is not None:
CẬP NHẬT: Giải thích thêm
Nhiều lần cả hai dường như làm điều tương tự nên rất nhiều người sử dụng chúng thay thế cho nhau - đó là một ý tưởng thực sự tồi tệ. Lý do cả hai đưa ra cùng một kết quả là nhiều lần bởi sự trùng hợp thuần túy do tối ưu hóa trình thông dịch / trình biên dịch như thực tập hoặc một cái gì đó khác.
Với những tối ưu hóa đó, các số nguyên và chuỗi có cùng giá trị sẽ sử dụng cùng một không gian bộ nhớ. Điều đó có thể giải thích tại sao hai chuỗi riêng biệt hoạt động như thể chúng giống nhau.
> a = 'test'
> b = 'test'
> a is b
True
> a == b
True
Những thứ khác không hành xử giống nhau mặc dù ..
> a = []
> b = []
> a is b
False
> a == b
True
Hai danh sách rõ ràng có bộ nhớ riêng của họ. Đáng ngạc nhiên tuples hành xử như chuỗi.
> a = ()
> b = ()
> a is b
True
> a == b
True
Có lẽ điều này là do các bộ dữ liệu được đảm bảo không thay đổi, do đó, nó có ý nghĩa để sử dụng lại cùng một bộ nhớ.
Điểm mấu chốt của vấn đề này là bạn không thể dựa vào sự trùng hợp . Chỉ vì nó quẫy như một con vịt, nó không có nghĩa là nó là một con vịt. Sử dụng isvà ==tùy thuộc vào những gì bạn thực sự muốn kiểm tra. Những điều này có thể khó gỡ lỗi vì isđọc như văn xuôi mà chúng ta thường chỉ đọc lướt qua nó.
Nonelà một singleton, nó không phải là một chi tiết triển khai (không giống như int hoặc chuỗi interning). Tôi không chắc là tôi làm theo ý bạn.
Nonehành vi khác hơn inthoặc strdo thực tập. Quan điểm của tôi là isvà ==đang kiểm tra những thứ khác nhau; đầu tiên kiểm tra một địa chỉ bộ nhớ, thứ hai kiểm tra nội dung của các địa chỉ bộ nhớ.
if A: sẽ chứng minh sai nếu A là 0, Sai, chuỗi trống, danh sách trống hoặc Không có, có thể dẫn đến kết quả không mong muốn.
Hầu hết các hướng dẫn tôi đã thấy đề xuất rằng bạn nên sử dụng
nếu một:
trừ khi bạn có một lý do để cụ thể hơn.
Có một số khác biệt nhỏ. Có các giá trị khác với Không có giá trị nào trả về Sai, ví dụ như danh sách trống hoặc 0, vì vậy hãy suy nghĩ về những gì bạn thực sự đang thử nghiệm.
Không có giá trị đặc biệt nào trong Python mà thường chỉ định một biến chưa được khởi tạo. Để kiểm tra xem A không có giá trị cụ thể này hay không, bạn sử dụng:
if A is not None
Giá trị Falsey là một lớp đối tượng đặc biệt trong Python (ví dụ: false, []). Để kiểm tra xem A có phải là falsey hay không:
if not A
Do đó, hai biểu thức không giống nhau Và tốt hơn hết bạn không nên coi chúng là từ đồng nghĩa.
PS Không cũng là falsey, vì vậy biểu thức đầu tiên ngụ ý thứ hai. Nhưng thứ hai bao gồm các giá trị falsey khác ngoài Không có. Bây giờ ... nếu bạn có thể chắc chắn rằng bạn không thể có các giá trị falsey khác ngoài Không có trong A, thì bạn có thể thay thế biểu thức đầu tiên bằng biểu thức thứ hai.
Nó phụ thuộc vào ngữ cảnh.
Tôi sử dụng if A:khi tôi mong đợi Alà một loại bộ sưu tập nào đó và tôi chỉ muốn thực thi khối nếu bộ sưu tập không trống. Điều này cho phép người gọi vượt qua bất kỳ bộ sưu tập nào hoạt động tốt, trống hay không và để nó thực hiện những gì tôi mong đợi. Nó cũng cho phép Nonevà Falsengăn chặn việc thực thi khối, đôi khi thuận tiện để gọi mã.
OTOH, nếu tôi dự kiến Alà một đối tượng hoàn toàn tùy ý nhưng nó có thể được mặc định None, thì tôi luôn sử dụng if A is not None, vì mã gọi có thể đã cố tình chuyển một tham chiếu đến một bộ sưu tập trống, chuỗi rỗng hoặc loại số có giá trị 0 hoặc boolean False, hoặc một số thể hiện lớp xảy ra là sai trong ngữ cảnh boolean.
Mặt khác, nếu tôi dự kiến Alà một số thứ cụ thể hơn (ví dụ: một lớp tôi sẽ gọi các phương thức của nó), nhưng nó có thể đã được mặc định Nonevà tôi coi chuyển đổi boolean mặc định là một thuộc tính của lớp tôi không ngại thực thi trên tất cả các lớp con, sau đó tôi sẽ chỉ sử dụng if A:để tiết kiệm cho ngón tay của mình gánh nặng khủng khiếp khi gõ thêm 12 ký tự.
Tôi đã tạo một tập tin được gọi test.pyvà chạy nó trên trình thông dịch. Bạn có thể thay đổi những gì bạn muốn, để kiểm tra chắc chắn mọi thứ đang diễn ra như thế nào đằng sau hậu trường.
import dis
def func1():
matchesIterator = None
if matchesIterator:
print( "On if." );
def func2():
matchesIterator = None
if matchesIterator is not None:
print( "On if." );
print( "\nFunction 1" );
dis.dis(func1)
print( "\nFunction 2" );
dis.dis(func2)
Đây là sự khác biệt của trình biên dịch:

Nguồn:
>>> import importlib
>>> reload( test )
Function 1
6 0 LOAD_CONST 0 (None)
3 STORE_FAST 0 (matchesIterator)
8 6 LOAD_FAST 0 (matchesIterator)
9 POP_JUMP_IF_FALSE 20
10 12 LOAD_CONST 1 ('On if.')
15 PRINT_ITEM
16 PRINT_NEWLINE
17 JUMP_FORWARD 0 (to 20)
>> 20 LOAD_CONST 0 (None)
23 RETURN_VALUE
Function 2
14 0 LOAD_CONST 0 (None)
3 STORE_FAST 0 (matchesIterator)
16 6 LOAD_FAST 0 (matchesIterator)
9 LOAD_CONST 0 (None)
12 COMPARE_OP 9 (is not)
15 POP_JUMP_IF_FALSE 26
18 18 LOAD_CONST 1 ('On if.')
21 PRINT_ITEM
22 PRINT_NEWLINE
23 JUMP_FORWARD 0 (to 26)
>> 26 LOAD_CONST 0 (None)
29 RETURN_VALUE
<module 'test' from 'test.py'>
trăn> = 2,6,
nếu chúng ta viết như
if A:
sẽ tạo cảnh báo như,
FutureWarning: Hành vi của phương pháp này sẽ thay đổi trong các phiên bản trong tương lai. Thay vào đó, hãy sử dụng thử nghiệm 'len (elem)' hoặc 'elem không phải là Không' cụ thể.
Vì vậy, chúng ta có thể sử dụng
if A is not None:
A is not Nonelà nhanh hơn vì có rất ít việc phải làm