objek null dengan Python?

1193

Bagaimana cara merujuk ke objek nol di Python?

Kadal
sumber

Jawaban:

1629

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:
    ...
Ben James
sumber
126
Dan alasan untuk memilih egg is Nonelebih egg == 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?) , sementara isselalu bekerja sama.
94
mengapa para desainer python tidak memilih "null". Hanya harus berbeda kan! ;)
Vidar
35
@Vidar 'Tidak Ada' bukan kekurangan objek (seperti 'nol' adalah, referensi nol), itu adalah objek yang sebenarnya. Anda tidak akan pernah mendapatkan objek 'Tidak Ada' yang lewat untuk objek yang sejenis selain 'Tidak Ada Jenis'. Ini juga bukan konsep bahasa .. Ini tidak dibangun untuk bahasa Python, itu bagian dari perpustakaan standar Python. Tidak ada! == (ahem) Null
Rushyo
11
@ naught101 Tidak ada gunanya; karena tidak ada konsep pointer. Jika Anda menggunakan pustaka ctypes, Tidak ada yang akan digunakan sebagai sinonim untuk alamat nol tetapi masih belum ada konsep bahasa 'referensi nol'. Dalam Python, Anda selalu meninggalkan referensi beberapa jenis objek, bahkan jika objek itu adalah None. Saya menduga ini sangat menyederhanakan bahasa.
Rushyo
5
presentasi hebat yang menjelaskan 'kesalahan miliar dolar' yang merupakan null ref: infoq.com/presentations/… . Pilihan lain alih-alih nol adalah Opsi, atau Mungkin (khusus) jenis.
Michael Trouw
135

None, Python nol?

Tidak ada nulldalam Python, melainkan ada None. Seperti yang telah dinyatakan, cara paling akurat untuk menguji bahwa sesuatu telah diberi Nonenilai adalah dengan menggunakan isoperator identitas, yang menguji dua variabel yang merujuk ke objek yang sama.

>>> foo is None
True
>>> foo = 'bar' 
>>> foo is None
False

Dasar

Ada dan hanya bisa satu None

Noneadalah satu-satunya instance dari kelas NoneTypedan setiap upaya lebih lanjut dalam membuat instance kelas yang akan mengembalikan objek yang sama, yang membuat Nonesingleton. Pendatang baru di Python sering melihat pesan kesalahan yang menyebutkan NoneTypedan bertanya-tanya apa itu. Ini adalah pendapat pribadi saya bahwa pesan-pesan ini hanya bisa disebutkan Nonenamanya saja, karena, seperti yang akan kita lihat sebentar lagi, Nonemenyisakan sedikit ruang bagi ambiguitas. Jadi, jika Anda melihat beberapa TypeErrorpesan yang menyebutkan bahwa NoneTypetidak dapat melakukan ini atau tidak dapat melakukannya, ketahuilah bahwa itu hanyalah pesan Noneyang digunakan dengan cara yang tidak dapat dilakukan.

Juga, Noneadalah konstanta bawaan, segera setelah Anda memulai Python tersedia untuk digunakan dari mana saja, baik dalam modul, kelas, atau fungsi. NoneTypesebaliknya tidak, Anda harus mendapatkan referensi terlebih dahulu dengan menanyakan Nonekelasnya.

>>> NoneType
NameError: name 'NoneType' is not defined
>>> type(None)
NoneType

Anda dapat memeriksa Nonekeunikan 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 ditimpa

Dalam 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 Nonereferensi adalah sama. Tidak ada "kebiasaan" None.

Untuk menguji Nonegunakan isoperator

Saat 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.

Kasus 1: menguji apakah nilainya None

kenapa melakukan ini

value is None

daripada

value==None

Yang pertama setara dengan:

id(value)==id(None)

Padahal ungkapan value==Noneitu sebenarnya diterapkan seperti ini

value.__eq__(None)

jika nilainya benar Nonemaka 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 Nonedan berhasil

>>> empty = Empty()
>>> empty==None
True

Tapi kemudian itu juga berfungsi pada string kosong

>>> empty==''
True

Dan lagi

>>> ''==None
False
>>> empty is None
False

Kasus 2: Menggunakan Nonesebagai boolean

Dua 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

Noneadalah "falsey", yang berarti bahwa jika dilemparkan ke boolean ia akan kembali Falsedan jika diterapkan notoperator itu akan kembali True. Namun perlu dicatat bahwa ini bukan properti unik untuk None. Selain itu Falsesendiri, 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 praktek

None digunakan sebagai nilai sinyal

Nonememiliki 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 Noneargumen 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 Noneketika 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 KeyErrorakan 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 valid

Penggunaan yang dijelaskan di atas Noneberlaku 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 Noneasalnya 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 Nonetidak memberi tahu Anda apakah atribut yang Anda coba akses diset ke Noneatau 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/exceptkonstruksi:

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 valid

Jika Anda menemukan bahwa kode Anda dikotori dengan try/exceptpola di atas hanya untuk membedakan antara Noneflag dan Nonedata, 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 Noneyang digunakan sebagai sinyal. Ini sepele untuk membuat sentinel dengan Python.

undefined = object()

The undefinedobjek di atas adalah unik dan tidak melakukan apa-apa yang mungkin menarik untuk sebuah program, itu sehingga pengganti yang sangat baik untuk Nonesebagai 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 undefineddi 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.

Michael Ekoka
sumber
Bagaimana dengan: Tidak ada == hal?
hkBst
@ hkBst Saya menduga pertanyaan Anda adalah tentang bagaimana python mengevaluasi kesetaraan. Lihatlah stackoverflow.com/questions/3588776/…
Michael Ekoka
Ah, jadi IIUC itu biasanya masih akan berakhir memanggil hal .__ eq__? Dalam hal ini saya menarik kembali saran saya.
hkBst
@MichaelEkoka dapat Anda bagikan sumber untuk informasi yang mengesankan dan bermanfaat ini.
Anidhya Bhatnagar
Praktik standar. Anda dapat menemukan beberapa petunjuk dari tutorial Python , tetapi membaca kode sumber proyek populer adalah saran nomor satu saya untuk segera membenamkan diri Anda ke dalam Python idiomatik .
Michael Ekoka
67

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.

AndiDog
sumber
25
Saya akan menemukan cara untuk memecahkan Python dengan re-instantiating None. Maka semua orang pintar yang dibandingkan dengan NoneTypeakan menang!
Zenexer
28

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:

Paolo Rovelli
sumber
8
Sejauh yang saya tahu, (0 == false) mengembalikan true IN SETIAP bahasa pemrograman. Itu karena false dikodekan sebagai 0 dan "benar" sebagai segala sesuatu yang TIDAK 0. Namun, harap tidak bahwa operator "adalah" tidak sama dengan yang "==". Perbedaan ini kurang lebih sama antara "==" dan "sama dengan" di Jawa. Operator "adalah", memang, memeriksa apakah DUA BENDA adalah sama (contoh yang sama dan BUKAN konten yang sama)!
Paolo Rovelli
12
Paolo, FYI, (0 == false) tidak mengembalikan true dalam setiap bahasa pemrograman. Contoh penghitung cepat adalah Scala, di mana (0 == false) mengembalikan false, dan saya yakin Scala bukan satu-satunya bahasa pemrograman yang mengembalikan false ketika membandingkan angka ke boolean.
Rob Wilton
2
OK mengerti! Kemudian, katakanlah dalam sebagian besar bahasa pemrograman.
Paolo Rovelli
3
Dalam JavaScript, alasannya 0 == falsekembali trueadalah karena operator double-equals mengetikkan paksaan. Namun, dengan operator triple-equals, 0 === falsepengembalian false, karena 'angka' dan 'boolean' adalah tipe yang berbeda.
jkdev
1
@ PaoloRovelli, di Lua, Ruby, dan Clojure, 0 diperlakukan sebagai truedalam kondisi. Di Rust and Go, 0dan false ada berbagai jenis yang tidak dapat dibandingkan untuk kesetaraan.
skuter menjuntai
0

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


sumber
-1

Pengujian nilai Per Truth , 'None' langsung menguji sebagai FALSE, jadi ungkapan paling sederhana akan cukup:

if not foo:
artejera
sumber
3
Tidak, tidak akan. Ekspresi yang akan kembali Trueuntuk setiap nilai falsy, bukan hanya None.
insert_name_here
Benar, dan sederhana "jika tidak foo:" tidak akan menjawab dengan benar pertanyaan awal, seperti yang dinyatakan. Namun, python diketik secara dinamis dan mengundang untuk mengurangi protokol sintaksis, sehingga tampaknya valid bagi saya, untuk mempertimbangkan konstruksi yang lebih sederhana dan serupa.
artejera