Jawaban:
Dalam Python, objek 'null' adalah singleton None
.
Cara terbaik untuk memeriksa hal-hal untuk "Noneness" adalah dengan menggunakan operator identitas, is
:
if foo is None:
...
None
, Python nol?Tidak ada null
dalam Python, melainkan ada None
. Seperti yang telah dinyatakan, cara paling akurat untuk menguji bahwa sesuatu telah diberi None
nilai adalah dengan menggunakan is
operator identitas, yang menguji dua variabel yang merujuk ke objek yang sama.
>>> foo is None
True
>>> foo = 'bar'
>>> foo is None
False
None
None
adalah satu-satunya instance dari kelas NoneType
dan setiap upaya lebih lanjut dalam membuat instance kelas yang akan mengembalikan objek yang sama, yang membuat None
singleton. Pendatang baru di Python sering melihat pesan kesalahan yang menyebutkan NoneType
dan bertanya-tanya apa itu. Ini adalah pendapat pribadi saya bahwa pesan-pesan ini hanya bisa disebutkan None
namanya saja, karena, seperti yang akan kita lihat sebentar lagi, None
menyisakan sedikit ruang bagi ambiguitas. Jadi, jika Anda melihat beberapa TypeError
pesan yang menyebutkan bahwa NoneType
tidak dapat melakukan ini atau tidak dapat melakukannya, ketahuilah bahwa itu hanyalah pesan None
yang digunakan dengan cara yang tidak dapat dilakukan.
Juga, None
adalah konstanta bawaan, segera setelah Anda memulai Python tersedia untuk digunakan dari mana saja, baik dalam modul, kelas, atau fungsi. NoneType
sebaliknya tidak, Anda harus mendapatkan referensi terlebih dahulu dengan menanyakan None
kelasnya.
>>> NoneType
NameError: name 'NoneType' is not defined
>>> type(None)
NoneType
Anda dapat memeriksa None
keunikan dengan fungsi identitas Python id()
. Ini mengembalikan nomor unik yang ditetapkan untuk suatu objek, masing-masing objek memiliki satu. Jika id dari dua variabel sama, maka mereka menunjuk ke objek yang sama.
>>> NoneType = type(None)
>>> id(None)
10748000
>>> my_none = NoneType()
>>> id(my_none)
10748000
>>> another_none = NoneType()
>>> id(another_none)
10748000
>>> def function_that_does_nothing(): pass
>>> return_value = function_that_does_nothing()
>>> id(return_value)
10748000
None
tidak dapat ditimpaDalam versi Python yang jauh lebih lama (sebelum 2.4) dimungkinkan untuk ditugaskan kembali None
, tetapi tidak lagi. Bahkan sebagai atribut kelas atau dalam batas fungsi.
# In Python 2.7
>>> class SomeClass(object):
... def my_fnc(self):
... self.None = 'foo'
SyntaxError: cannot assign to None
>>> def my_fnc():
None = 'foo'
SyntaxError: cannot assign to None
# In Python 3.5
>>> class SomeClass:
... def my_fnc(self):
... self.None = 'foo'
SyntaxError: invalid syntax
>>> def my_fnc():
None = 'foo'
SyntaxError: cannot assign to keyword
Karenanya aman untuk mengasumsikan bahwa semua None
referensi adalah sama. Tidak ada "kebiasaan" None
.
None
gunakan is
operatorSaat menulis kode, Anda mungkin tergoda untuk menguji Noneness seperti ini:
if value==None:
pass
Atau untuk menguji kepalsuan seperti ini
if not value:
pass
Anda perlu memahami implikasinya dan mengapa itu sering merupakan ide yang baik untuk menjadi eksplisit.
None
kenapa melakukan ini
value is None
daripada
value==None
Yang pertama setara dengan:
id(value)==id(None)
Padahal ungkapan value==None
itu sebenarnya diterapkan seperti ini
value.__eq__(None)
jika nilainya benar None
maka Anda akan mendapatkan apa yang Anda harapkan.
>>> nothing = function_that_does_nothing()
>>> nothing.__eq__(None)
True
Dalam kebanyakan kasus, hasilnya akan sama, tetapi __eq__()
metode ini membuka pintu yang membatalkan jaminan keakuratan, karena dapat ditimpa dalam kelas untuk memberikan perilaku khusus.
Pertimbangkan kelas ini.
>>> class Empty(object):
... def __eq__(self, other):
... return not other
Jadi Anda mencobanya None
dan berhasil
>>> empty = Empty()
>>> empty==None
True
Tapi kemudian itu juga berfungsi pada string kosong
>>> empty==''
True
Dan lagi
>>> ''==None
False
>>> empty is None
False
None
sebagai booleanDua tes berikut
if value:
# do something
if not value:
# do something
sebenarnya dievaluasi sebagai
if bool(value):
# do something
if not bool(value):
# do something
None
adalah "falsey", yang berarti bahwa jika dilemparkan ke boolean ia akan kembali False
dan jika diterapkan not
operator itu akan kembali True
. Namun perlu dicatat bahwa ini bukan properti unik untuk None
. Selain itu False
sendiri, properti dibagi oleh daftar kosong, tupel, set, dikte, string, serta 0, dan semua objek dari kelas yang menerapkan __bool__()
metode ajaib untuk kembali False
.
>>> bool(None)
False
>>> not None
True
>>> bool([])
False
>>> not []
True
>>> class MyFalsey(object):
... def __bool__(self):
... return False
>>> f = MyFalsey()
>>> bool(f)
False
>>> not f
True
Jadi saat menguji variabel dengan cara berikut, waspadalah dengan apa yang Anda sertakan atau tidak termasuk dalam tes:
def some_function(value=None):
if not value:
value = init_value()
Di atas, apakah Anda bermaksud menelepon init_value()
saat nilai diatur secara khusus None
, atau apakah Anda maksud bahwa nilai ditetapkan 0
, atau string kosong, atau daftar kosong juga harus memicu inisialisasi. Seperti yang saya katakan, berhati-hatilah. Seperti yang sering terjadi dalam Python eksplisit lebih baik daripada implisit .
None
dalam praktekNone
digunakan sebagai nilai sinyalNone
memiliki status khusus dalam Python. Ini adalah nilai dasar favorit karena banyak algoritma memperlakukannya sebagai nilai luar biasa. Dalam skenario seperti itu dapat digunakan sebagai tanda untuk memberi sinyal bahwa suatu kondisi memerlukan penanganan khusus (seperti pengaturan nilai default).
Anda dapat menetapkan None
argumen kata kunci dari suatu fungsi dan kemudian secara eksplisit mengujinya.
def my_function(value, param=None):
if param is None:
# do something outrageous!
Anda dapat mengembalikannya sebagai default ketika mencoba untuk mendapatkan atribut objek dan kemudian secara eksplisit mengujinya sebelum melakukan sesuatu yang istimewa.
value = getattr(some_obj, 'some_attribute', None)
if value is None:
# do something spectacular!
Secara default metode kamus get()
kembali None
ketika mencoba mengakses kunci yang tidak ada:
>>> some_dict = {}
>>> value = some_dict.get('foo')
>>> value is None
True
Jika Anda mencoba mengaksesnya dengan menggunakan notasi subskrip, maka KeyError
akan dimunculkan
>>> value = some_dict['foo']
KeyError: 'foo'
Demikian juga jika Anda mencoba memunculkan item yang tidak ada
>>> value = some_dict.pop('foo')
KeyError: 'foo'
yang dapat Anda tekan dengan nilai default yang biasanya diatur ke None
value = some_dict.pop('foo', None)
if value is None:
# booom!
None
digunakan sebagai bendera dan nilai yang validPenggunaan yang dijelaskan di atas None
berlaku ketika tidak dianggap sebagai nilai yang valid, tetapi lebih seperti sinyal untuk melakukan sesuatu yang istimewa. Namun ada situasi di mana kadang-kadang penting untuk mengetahui dari mana None
asalnya karena meskipun itu digunakan sebagai sinyal itu juga bisa menjadi bagian dari data.
Saat Anda meminta objek untuk atributnya dengan getattr(some_obj, 'attribute_name', None)
membalas None
tidak memberi tahu Anda apakah atribut yang Anda coba akses diset ke None
atau jika itu sama sekali tidak ada dari objek. Situasi yang sama ketika mengakses kunci dari kamus seperti some_dict.get('some_key')
, Anda tidak tahu apakah some_dict['some_key']
ada yang hilang atau hanya diatur ke None
. Jika Anda memerlukan informasi itu, cara biasa untuk menangani ini adalah dengan langsung mencoba mengakses atribut atau kunci dari dalam sebuah try/except
konstruksi:
try:
# equivalent to getattr() without specifying a default
# value = getattr(some_obj, 'some_attribute')
value = some_obj.some_attribute
# now you handle `None` the data here
if value is None:
# do something here because the attribute was set to None
except AttributeError:
# we're now hanling the exceptional situation from here.
# We could assign None as a default value if required.
value = None
# In addition, since we now know that some_obj doesn't have the
# attribute 'some_attribute' we could do something about that.
log_something(some_obj)
Demikian pula dengan dikt:
try:
value = some_dict['some_key']
if value is None:
# do something here because 'some_key' is set to None
except KeyError:
# set a default
value = None
# and do something because 'some_key' was missing
# from the dict.
log_something(some_dict)
Dua contoh di atas menunjukkan bagaimana menangani kasus objek dan kamus, bagaimana dengan fungsi? Hal yang sama, tetapi kami menggunakan argumen kata kunci tanda bintang ganda untuk tujuan itu:
def my_function(**kwargs):
try:
value = kwargs['some_key']
if value is None:
# do something because 'some_key' is explicitly
# set to None
except KeyError:
# we assign the default
value = None
# and since it's not coming from the caller.
log_something('did not receive "some_key"')
None
hanya digunakan sebagai nilai yang validJika Anda menemukan bahwa kode Anda dikotori dengan try/except
pola di atas hanya untuk membedakan antara None
flag dan None
data, maka gunakan saja nilai tes lain. Ada pola di mana nilai yang berada di luar rangkaian nilai yang valid dimasukkan sebagai bagian dari data dalam struktur data dan digunakan untuk mengontrol dan menguji kondisi khusus (misalnya batas, keadaan, dll). Nilai seperti ini disebut sentinel dan dapat digunakan dengan cara None
yang digunakan sebagai sinyal. Ini sepele untuk membuat sentinel dengan Python.
undefined = object()
The undefined
objek di atas adalah unik dan tidak melakukan apa-apa yang mungkin menarik untuk sebuah program, itu sehingga pengganti yang sangat baik untuk None
sebagai bendera. Beberapa peringatan berlaku, lebih lanjut tentang hal itu setelah kode.
Dengan fungsi
def my_function(value, param1=undefined, param2=undefined):
if param1 is undefined:
# we know nothing was passed to it, not even None
log_something('param1 was missing')
param1 = None
if param2 is undefined:
# we got nothing here either
log_something('param2 was missing')
param2 = None
Dengan dikt
value = some_dict.get('some_key', undefined)
if value is None:
log_something("'some_key' was set to None")
if value is undefined:
# we know that the dict didn't have 'some_key'
log_something("'some_key' was not set at all")
value = None
Dengan sebuah benda
value = getattr(obj, 'some_attribute', undefined)
if value is None:
log_something("'obj.some_attribute' was set to None")
if value is undefined:
# we know that there's no obj.some_attribute
log_something("no 'some_attribute' set on obj")
value = None
Seperti yang saya sebutkan sebelumnya penjaga adat datang dengan beberapa peringatan. Pertama, itu bukan kata kunci None
, jadi python tidak melindunginya. Anda dapat menimpa undefined
di atas kapan saja, di mana saja dalam modul yang ditentukan, jadi berhati-hatilah bagaimana Anda mengekspos dan menggunakannya. Selanjutnya, instance yang dikembalikan oleh object()
bukan singleton, jika Anda melakukan panggilan itu 10 kali Anda mendapatkan 10 objek yang berbeda. Akhirnya, penggunaan sentinel sangat istimewa. Sentinel khusus untuk perpustakaan yang digunakan dan karenanya cakupannya umumnya harus dibatasi untuk internal perpustakaan. Seharusnya tidak "bocor" keluar. Kode eksternal seharusnya hanya menyadarinya, jika tujuannya adalah untuk memperluas atau menambah API perpustakaan.
Ini tidak disebut null seperti dalam bahasa lain, tetapi None
. Selalu ada hanya satu instance dari objek ini, sehingga Anda dapat memeriksa kesetaraan dengan x is None
(perbandingan identitas), bukan x == None
, jika Anda mau.
None
. Maka semua orang pintar yang dibandingkan dengan NoneType
akan menang!
Dalam Python, untuk mewakili tidak adanya nilai, Anda dapat menggunakan nilai None ( types.NoneType.None ) untuk objek dan "" (atau len () == 0 ) untuk string. Karena itu:
if yourObject is None: # if yourObject == None:
...
if yourString == "": # if yourString.len() == 0:
...
Mengenai perbedaan antara "==" dan "adalah", pengujian untuk identitas objek menggunakan "==" harus memadai. Namun, karena operasi "adalah" didefinisikan sebagai operasi identitas objek, mungkin lebih tepat untuk menggunakannya, daripada "==". Tidak yakin apakah ada perbedaan kecepatan.
Bagaimanapun, Anda dapat melihat:
0 == false
kembali true
adalah karena operator double-equals mengetikkan paksaan. Namun, dengan operator triple-equals, 0 === false
pengembalian false
, karena 'angka' dan 'boolean' adalah tipe yang berbeda.
true
dalam kondisi. Di Rust and Go, 0
dan false
ada berbagai jenis yang tidak dapat dibandingkan untuk kesetaraan.
Null adalah jenis objek khusus seperti:
>>>type(None)
<class 'NoneType'>
Anda dapat memeriksa apakah suatu objek ada di kelas 'NoneType':
>>>variable = None
>>>variable is None
True
Informasi lebih lanjut tersedia di Python Docs
Pengujian nilai Per Truth , 'None' langsung menguji sebagai FALSE, jadi ungkapan paling sederhana akan cukup:
if not foo:
True
untuk setiap nilai falsy, bukan hanya None
.
egg is None
lebihegg == None
: Yang terakhir dapat kelebihan beban, dan cenderung rusak ketika membandingkan objek yang valid dengan Tidak Ada (tergantung pada bagaimana itu diterapkan, tetapi Anda tidak mengharapkan semua orang untuk mengambil perbandingan dengan Tidak Ada ke dalam akun, bukan?) , sementarais
selalu bekerja sama.