Mogę uzyć:
if A:
zamiast
if A is not None:
Ta ostatnia wydaje się taka gadatliwa. Czy jest jakaś różnica?
Twierdzenie
if A:
wywoła A.__nonzero__()
(zobacz dokumentację nazw metod specjalnych ) i użyje wartości zwracanej przez tę funkcję. Oto podsumowanie:
object.__nonzero__(self)
Wezwany do wdrożenia testowania wartości prawdy i wbudowanej operacji
bool()
; powinny zwrócićFalse
orTrue
, lub ich odpowiedniki w postaci liczb całkowitych0
lub1
. Gdy ta metoda nie jest zdefiniowana,__len__()
jest wywoływana, jeśli jest zdefiniowana, a obiekt jest uważany za prawdziwy, jeśli jego wynik jest różny od zera. Jeśli klasa nie definiuje__len__()
ani__nonzero__()
, wszystkie jej wystąpienia są uznawane za prawdziwe.
Z drugiej strony,
if A is not None:
porównuje tylko odniesienie A
z, None
aby zobaczyć, czy jest takie samo, czy nie.
A is not None
jest szybciej, ponieważ jest znacznie mniej do zrobieniaif object(): pass
wynosi ~ 0,130 usek na pętlę, podczas gdyif object() is not None: pass
wynosi ~ 0,135 usek. W każdym razie nie powinieneś używać wydajności do wyboru między tymi dwoma, ale raczej przyjrzyj się różnicom w ich działaniu, ponieważ nie są one równoważne .if A is not None
wydaje się być wolniejszy, ponieważ jest to porównanie i musi załadować wbudowany singletonNone
jako pośredni krok do porównaniaA
(spójrz nadis.dis()
). Popraw mnie, jeśli się mylę, aleif A:
wydaje się być skuteczniejszy, gdy tylko naprawdę chcesz sprawdzić wartość prawdy, a nieNone
tożsamość.python -m timeit -s"a=0" "if a: pass" "else: pass"
jest szybszy niż,python -m timeit -s"a=0" "if a is None: pass" "else: pass"
alepython -m timeit -s"a=1" "if a: pass" "else: pass"
jest wolniejszy. Może być zależne od platformy, zobacz, czy uzyskasz takie same wynikiis None
test był dla mnie rzeczywiście najwolniejszy. W pypy wszyscy mierzyli dokładnie tak samo :)Jak napisano w PEP8 :
źródło
None
, a jedynie sprawdzenie wartości prawdy. W tym przypadkuif A:
wydaje się bardziej wydajne (weźdis.dis()
, są dodatkowe kroki wczytywania wbudowanegoNone
i porównywaniaif A is not None:
, podczas gdyjump_if
w drugim przypadku jest tylko a ).więc to nie to samo, co
źródło
Wiele funkcji zwraca None, jeśli nie ma odpowiednich wyników. Na przykład
.first()
metoda zapytania SQLAlchemy zwraca wartość None, jeśli w wyniku nie ma żadnych wierszy. Załóżmy, że wybierasz wartość, która może zwrócić 0 i musisz wiedzieć, czy w rzeczywistości jest to 0, czy też zapytanie nie dało żadnych wyników.Typowym idiomem jest przypisanie opcjonalnemu argumentowi funkcji lub metody domyślnej wartości None, a następnie przetestowanie tej wartości jako None, aby sprawdzić, czy została określona. Na przykład:
porównaj to z:
W drugim przypadku, co się stanie, jeśli zadzwonisz
spam(0)
lubspam([])
? Funkcja wykryłaby (niepoprawnie), że nie przekazałeś wartości dlaeggs
i obliczyłaby dla ciebie wartość domyślną. Prawdopodobnie nie tego chcesz.Albo wyobraź sobie metodę typu „zwróć listę transakcji dla danego konta”. Jeśli konto nie istnieje, może zwrócić Brak. Różni się to od zwrócenia pustej listy (co oznaczałoby, że „to konto istnieje, ale nie zarejestrowało transakcji).
Wreszcie wróćmy do bazy danych. Istnieje duża różnica między wartością NULL a pustym ciągiem. Pusty ciąg zwykle mówi „jest tutaj wartość, a ta wartość jest niczym”. NULL mówi „ta wartość nie została wprowadzona”.
W każdym z tych przypadków chciałbyś użyć
if A is None
. Sprawdzasz określoną wartość - None - a nie tylko „jakąkolwiek wartość, która zdarzy się rzutować na False”.źródło
Robią bardzo różne rzeczy .
Poniższe sprawdza czy ma nic oprócz wartości
False
,[]
,None
,''
i0
. Sprawdza wartość A.Poniższe sprawdza, czy A jest innym obiektem niż Brak. Sprawdza i porównuje odniesienie (adres pamięci) A i None.
UPDATE: Dalsze wyjaśnienia
Wiele razy wydaje się, że robią to samo, więc wiele osób używa ich zamiennie - to naprawdę zły pomysł. Powodem, dla którego oba dają te same wyniki, jest wiele razy czysty przypadek z powodu optymalizacji interpretera / kompilatora, takich jak interning lub coś innego.
Mając na uwadze te optymalizacje, liczby całkowite i ciągi o tej samej wartości używają tego samego miejsca w pamięci. To prawdopodobnie wyjaśnia, dlaczego dwa oddzielne ciągi działają tak, jakby były takie same.
Jednak inne rzeczy nie zachowują się tak samo.
Obie listy najwyraźniej mają swoją własną pamięć. Zaskakująco krotki zachowują się jak struny.
Prawdopodobnie wynika to z faktu, że krotki na pewno się nie zmienią, dlatego warto ponownie użyć tej samej pamięci.
Podsumowując, nie można polegać na zbiegach okoliczności . To, że kwacze jak kaczka, nie oznacza, że jest kaczką. Użyj
is
iw==
zależności od tego, co naprawdę chcesz sprawdzić. Te rzeczy mogą być trudne do debugowania, ponieważis
czyta się jak proza, którą często po prostu przeglądamy.źródło
None
jest singletonem, nie jest szczegółem implementacji (w przeciwieństwie do internowania int lub string). Nie jestem pewien, czy rozumiem to, co masz na myśli.None
zachowuje się inaczejint
lub zstr
powodu internowania. Chodzi mi o tois
i==
sprawdzam różne rzeczy; pierwszy sprawdza adres pamięci, drugi sprawdza zawartość adresów pamięci.if A:
okaże się fałszywe, jeśli A ma wartość 0, Fałsz, pusty ciąg, pustą listę lub Brak, co może prowadzić do niepożądanych wyników.źródło
Większość przewodników, które widziałem, sugeruje, że powinieneś użyć
Jeśli:
chyba że masz powód, by być bardziej szczegółowym.
Jest kilka drobnych różnic. Istnieją wartości inne niż None, które zwracają False, na przykład puste listy lub 0, więc zastanów się, do czego naprawdę testujesz.
źródło
None to specjalna wartość w Pythonie, która zwykle oznacza niezainicjowaną zmienną. Aby sprawdzić, czy A nie ma tej konkretnej wartości, użyj:
Wartości Falsey to specjalna klasa obiektów w Pythonie (np. False, []). Aby sprawdzić, czy A to błąd, użyj:
Zatem te dwa wyrażenia nie są takie same I lepiej nie traktować ich jako synonimów.
PS Brak jest również błędem, więc pierwsze wyrażenie implikuje drugie. Ale druga obejmuje inne fałszywe wartości oprócz None. Teraz ... jeśli możesz być pewien, że nie możesz mieć innych wartości falsey poza None w A, możesz zastąpić pierwsze wyrażenie drugim.
źródło
To zależy od kontekstu.
Używam,
if A:
gdy spodziewamA
się, że będzie to jakaś kolekcja, i chcę wykonać blok tylko wtedy, gdy kolekcja nie jest pusta. Dzięki temu dzwoniący może przekazać każdą dobrze wychowaną kolekcję, pustą lub nie, i zrobić to, czego oczekuję. Umożliwia równieżNone
iFalse
wstrzymuje wykonanie bloku, co jest czasami wygodne do wywołania kodu.OTOH, jeśli spodziewam
A
się, że będzie to jakiś całkowicie dowolny obiekt, ale mógł zostać ustawiony domyślnieNone
, to zawsze używamif A is not None
, ponieważ kod wywołujący mógł celowo przekazać odwołanie do pustej kolekcji, pustego ciągu lub typu liczbowego o wartości 0, lub booleanFalse
lub jakaś instancja klasy, która jest fałszywa w kontekście boolowskim.Z drugiej strony, jeśli spodziewam
A
się, że będzie to coś bardziej szczegółowego (np. Instancja klasy, której mam zamiar wywołać metody), ale mogłaNone
zostać ustawiona domyślnie i uważam, że domyślna konwersja boolowska jest właściwość klasy, której nie mam nic przeciwko narzucaniu wszystkim podklasom, wtedy po prostuif A:
oszczędzę palcom strasznego ciężaru wpisywania dodatkowych 12 znaków.źródło
Utworzyłem plik o nazwie
test.py
i uruchomiłem go na tłumaczu. Możesz zmienić to, co chcesz, aby sprawdzić na pewno, jak to się dzieje za kulisami.To jest różnica w assemblerze:
Źródło:
źródło
Pierwsza jest bardziej Pythonowa (lepszy kod ideomatyczny), ale nie wykona bloku, jeśli A jest fałszywe (nie brak).
źródło
is/is not None
. Po PEP8 jest Pythonic. Poza tym dwa testy są różne .python> = 2.6,
jeśli napiszemy np
wygeneruje ostrzeżenie,
Więc możemy użyć
źródło