Bisakah saya menggunakan:
if A:
dari pada
if A is not None:
Yang terakhir tampaknya sangat bertele-tele. Apakah ada perbedaan?
Pernyataan
if A:
akan memanggil A.__nonzero__()
(lihat dokumentasi Nama metode khusus ) dan menggunakan nilai balik dari fungsi itu. Berikut ringkasannya:
object.__nonzero__(self)
Dipanggil untuk menerapkan pengujian nilai kebenaran dan operasi internal
bool()
; harus mengembalikanFalse
atauTrue
, atau setara dengan bilangan bulatnya0
atau1
. Ketika metode ini tidak didefinisikan,__len__()
dipanggil, jika didefinisikan, dan objek dianggap benar jika hasilnya nol. Jika suatu kelas tidak mendefinisikan__len__()
atau pun tidak__nonzero__()
, semua instance-nya dianggap benar.
Di samping itu,
if A is not None:
hanya membandingkan referensi A
dengan None
untuk melihat apakah itu sama atau tidak.
A is not None
lebih cepat karena ada jauh lebih sedikit pekerjaan yang harus dilakukanif object(): pass
adalah ~ 0,130 usec per loop, sedangkanif object() is not None: pass
~ 0,135 usec. Pokoknya, Anda tidak boleh menggunakan kinerja untuk memilih di antara keduanya, melainkan melihat perbedaan dalam cara kerjanya, karena keduanya tidak setara .if A is not None
tampaknya lebih lambat karena ini merupakan perbandingan dan perlu memuat singleton builtinNone
sebagai langkah perantara untuk membandingkanA
(lihat didis.dis()
). Perbaiki saya jika saya salah tetapiif A:
tampaknya lebih efisien, segera setelah Anda benar-benar ingin menguji nilai kebenaran dan bukanNone
identitasnya.python -m timeit -s"a=0" "if a: pass" "else: pass"
lebih cepat daripadapython -m timeit -s"a=0" "if a is None: pass" "else: pass"
tetapipython -m timeit -s"a=1" "if a: pass" "else: pass"
lebih lambat. Mungkin tergantung pada platform, lihat apakah Anda mendapatkan hasil yang samais None
tes itu memang paling lambat bagi saya. Dalam pypy mereka semua mengukur persis sama :)Seperti yang tertulis dalam PEP8 :
sumber
None
, tetapi hanya dalam pengecekan nilai kebenaran. Dalam hal ini,if A:
tampaknya lebih efisien (ambil adis.dis()
, ada langkah-langkah tambahan memuat builtinNone
dan membandingkan, denganif A is not None:
, sementara hanya adajump_if
dalam kasus lain).jadi tidak sama dengan
sumber
Banyak fungsi kembali Tidak ada jika tidak ada hasil yang sesuai. Misalnya, metode kueri SQLAlchemy
.first()
mengembalikan None jika tidak ada baris dalam hasilnya. Misalkan Anda memilih nilai yang mungkin mengembalikan 0 dan perlu tahu apakah itu sebenarnya 0 atau apakah kueri tidak memiliki hasil sama sekali.Sebuah idiom umum adalah untuk memberikan argumen opsional fungsi atau metode nilai default Tidak ada, dan kemudian untuk menguji nilai yang menjadi Tidak ada untuk melihat apakah itu ditentukan. Sebagai contoh:
bandingkan dengan:
Dalam yang terakhir, apa yang terjadi jika Anda menelepon
spam(0)
atauspam([])
? Fungsi akan (secara keliru) mendeteksi bahwa Anda belum memberikan nilai untukeggs
dan akan menghitung nilai default untuk Anda. Mungkin itu bukan yang Anda inginkan.Atau bayangkan metode seperti "kembalikan daftar transaksi untuk akun yang diberikan". Jika akun tidak ada, itu mungkin mengembalikan Tidak Ada. Ini berbeda dengan mengembalikan daftar kosong (yang berarti "akun ini ada tetapi belum mencatat transaksi).
Akhirnya, kembali ke basis data. Ada perbedaan besar antara NULL dan string kosong. String kosong biasanya mengatakan "ada nilai di sini, dan nilai itu tidak ada artinya sama sekali". NULL mengatakan "nilai ini belum dimasukkan."
Dalam setiap kasus tersebut, Anda ingin menggunakannya
if A is None
. Anda memeriksa nilai tertentu - Tidak ada - bukan hanya "nilai apa pun yang terjadi pada False".sumber
Mereka melakukan hal yang sangat berbeda .
Di bawah memeriksa apakah A memiliki apa-apa kecuali nilai-nilai
False
,[]
,None
,''
dan0
. Ia memeriksa nilai A.Di bawah ini memeriksa apakah A adalah objek yang berbeda dari Tidak Ada. Ia memeriksa dan membandingkan referensi (alamat memori) A dan None.
PEMBARUAN: Penjelasan lebih lanjut
Sering kali keduanya tampaknya melakukan hal yang sama sehingga banyak orang menggunakannya secara bergantian - itu ide yang sangat buruk. Alasan keduanya memberikan hasil yang sama berkali-kali karena kebetulan murni karena optimalisasi penerjemah / kompiler seperti magang atau sesuatu yang lain.
Dengan adanya optimasi tersebut, bilangan bulat dan string dengan nilai yang sama berakhir menggunakan ruang memori yang sama. Itu mungkin menjelaskan mengapa dua string terpisah bertindak seolah-olah mereka sama.
Hal-hal lain tidak berperilaku sama ..
Kedua daftar jelas memiliki ingatan mereka sendiri. Tuple yang mengejutkan berperilaku seperti string.
Mungkin ini karena tuple dijamin tidak berubah, jadi masuk akal untuk menggunakan kembali memori yang sama.
Intinya adalah bahwa Anda tidak dapat bergantung pada kebetulan . Hanya karena dukun seperti bebek itu tidak berarti itu bebek. Gunakan
is
dan==
tergantung pada apa yang benar-benar ingin Anda periksa. Hal-hal ini bisa sulit untuk di-debug karenais
terbaca seperti prosa yang sering kita selipkan saja.sumber
None
adalah singleton, ini bukan detail implementasi (tidak seperti int atau string magang). Saya tidak yakin saya mengikuti apa yang Anda maksud.None
berperilaku berbeda dariint
ataustr
karena magang. Maksud saya adalahis
dan==
memeriksa berbagai hal; pertama memeriksa alamat memori, yang kedua memeriksa isi alamat memori.if A:
akan terbukti salah jika A adalah 0, False, string kosong, daftar kosong atau Tidak ada, yang dapat menyebabkan hasil yang tidak diinginkan.sumber
Sebagian besar panduan yang pernah saya lihat menyarankan agar Anda gunakan
jika sebuah:
kecuali Anda memiliki alasan untuk lebih spesifik.
Ada beberapa perbedaan kecil. Ada nilai selain Tidak ada yang mengembalikan False, misalnya daftar kosong, atau 0, jadi pikirkan apa yang sebenarnya Anda uji.
sumber
Tidak ada nilai khusus dalam Python yang biasanya menunjuk variabel tidak diinisialisasi. Untuk menguji apakah A tidak memiliki nilai khusus ini yang Anda gunakan:
Nilai-nilai Falsey adalah kelas objek khusus dalam Python (mis false, []). Untuk menguji apakah A palsu, gunakan:
Dengan demikian, kedua ungkapan itu tidak sama dan Anda sebaiknya tidak memperlakukannya sebagai sinonim.
PS None juga falsey, jadi ekspresi pertama menyiratkan yang kedua. Tetapi yang kedua mencakup nilai-nilai falsey lain selain Tidak Ada. Sekarang ... jika Anda dapat memastikan bahwa Anda tidak dapat memiliki nilai falsey lain selain None di A, maka Anda dapat mengganti ekspresi pertama dengan yang kedua.
sumber
Itu tergantung pada konteksnya.
Saya menggunakan
if A:
ketika saya berharapA
akan menjadi semacam koleksi, dan saya hanya ingin menjalankan blok jika koleksi tidak kosong. Hal ini memungkinkan penelepon untuk melewati koleksi yang berperilaku baik, kosong atau tidak, dan membuatnya melakukan apa yang saya harapkan. Ini juga memungkinkanNone
danFalse
untuk menekan eksekusi blok, yang kadang-kadang nyaman untuk memanggil kode.OTOH, jika saya berharap
A
menjadi objek yang sepenuhnya arbitrer tetapi bisa saja defaultNone
, maka saya selalu menggunakanif A is not None
, karena kode panggilan bisa dengan sengaja memberikan referensi ke koleksi kosong, string kosong, atau tipe numerik bernilai 0, atau booleanFalse
, atau beberapa instance kelas yang kebetulan salah dalam konteks boolean.Dan di sisi lain, jika saya berharap
A
menjadi beberapa hal yang lebih spesifik (misalnya instance dari kelas yang akan saya panggil metode), tapi itu bisa saja defaultNone
, dan saya menganggap konversi boolean default menjadi properti dari kelas yang saya tidak keberatan menerapkan pada semua subclass, maka saya hanya akan menggunakanif A:
untuk menyelamatkan jari-jari saya dari mengetik 12 karakter ekstra.sumber
Saya membuat file yang dipanggil
test.py
dan menjalankannya pada interpreter. Anda dapat mengubah apa yang Anda inginkan, untuk menguji dengan pasti bagaimana keadaan di balik layar.Ini adalah perbedaan assembler:
Sumber:
sumber
Yang pertama lebih Pythonic (kode ideomatik yang lebih baik), tetapi tidak akan mengeksekusi blok jika A adalah False (bukan None).
sumber
is/is not None
. Mengikuti PEP8 adalah Pythonic. Selain itu kedua tes berbeda .python> = 2.6,
jika kita menulis seperti
akan menghasilkan peringatan seperti,
Jadi bisa kita gunakan
sumber