Pertanyaan objek nol dengan Python?


Bagaimana saya merujuk ke objek nol dengan Python?


804
2017-07-20 11:53


asal


Jawaban:


Dalam Python, objek 'nol' adalah tunggal None.

Cara terbaik untuk memeriksa hal-hal "Noneness" adalah dengan menggunakan operator identitas, is:

if foo is None:
    ...

1119
2017-07-20 11:54



Ini tidak disebut null seperti dalam bahasa lain, tetapi None. Hanya ada satu contoh objek ini, jadi Anda dapat memeriksa kesetaraan dengan x is None (Pembandingan identitas) sebagai gantinya x == None, jika kamu mau.


53
2017-07-20 11:56



Dalam Python, untuk mewakili ketiadaan nilai, Anda dapat menggunakan Tidak ada nilai (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 "==" seharusnya cukup. Namun, karena operasi "adalah" didefinisikan sebagai operasi identitas objek, mungkin lebih tepat untuk menggunakannya, daripada "==". Tidak yakin apakah bahkan ada perbedaan kecepatan.

Bagaimanapun, Anda dapat melihat:


26
2018-03-03 11:11



None, Python tidak ada?

Tidak ada null dengan Python, sebaliknya ada None. Sebagaimana dinyatakan sudah cara paling akurat untuk menguji sesuatu yang telah diberikan None sebagai nilai adalah menggunakan is operator identitas, yang menguji bahwa dua variabel mengacu pada objek yang sama.

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

Dasar

Ada dan hanya ada satu None

None adalah satu-satunya kelas NoneType dan setiap upaya lebih lanjut untuk instantiate kelas tersebut akan mengembalikan objek yang sama, yang membuatnya None seorang tunggal. Pendatang baru ke Python sering melihat pesan kesalahan yang disebutkan NoneType dan bertanya-tanya apa itu. Itu pendapat pribadi saya bahwa pesan-pesan ini bisa disebutkan begitu saja None dengan nama karena, seperti yang akan kita lihat sebentar lagi, None menyisakan sedikit ruang untuk ambiguitas. Jadi, jika Anda melihat beberapa TypeError pesan yang menyebutkan itu NoneType tidak bisa melakukan ini atau tidak bisa melakukannya, ketahuilah bahwa itu hanya salah satunya None yang digunakan dengan cara yang tidak bisa.

Juga, None adalah konstanta built-in, segera setelah Anda memulai Python, ini dapat digunakan dari mana saja, baik dalam modul, kelas, atau fungsi. NoneType sebaliknya tidak, Anda harus mendapatkan referensi terlebih dahulu dengan query None untuk kelasnya.

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

Anda bisa memeriksanya NoneKeunikan dengan fungsi identitas Python id(). Ini mengembalikan nomor unik yang ditugaskan ke suatu objek, setiap objek memiliki satu. Jika id dari dua variabel itu sama, maka mereka menunjuk pada fakta 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 banyak versi Python (sebelum 2,4) dimungkinkan untuk menetapkan kembali None, tapi tidak lagi. Bahkan sebagai atribut kelas atau dalam batas-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

Oleh karena itu aman untuk menganggap itu semua None referensi adalah sama. Tidak ada "kebiasaan" None.

Untuk menguji None menggunakan is operator

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 sering ide yang bagus untuk menjadi eksplisit.

Kasus 1: menguji apakah suatu nilai None

kenapa melakukan ini

value is None

daripada

value==None

Yang pertama setara dengan:

id(value)==id(None)

Padahal ungkapannya value==None sebenarnya diterapkan seperti ini

value.__eq__(None)

jika nilainya benar-benar None maka Anda akan mendapatkan apa yang Anda harapkan.

>>> nothing = function_that_does_nothing()
>>> nothing.__eq__(None)
True

Dalam kebanyakan kasus umum hasilnya akan sama, tetapi __eq__() metode membuka pintu yang tidak menjamin jaminan apa pun, karena dapat dikesampingkan di kelas untuk memberikan perilaku khusus.

Pertimbangkan kelas ini.

>>> class Empty(object):
...     def __eq__(self, other):
...         return not other

Jadi Anda mencobanya None dan itu 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 None sebagai 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

None adalah "falsey", artinya jika dilemparkan ke boolean ia akan kembali False dan jika diterapkan not operator itu akan kembali True. Namun perlu dicatat bahwa itu bukan properti yang unik None. Sebagai tambahannya False itu sendiri, properti dibagi oleh daftar kosong, tupel, set, dicts, string, serta 0, dan semua objek dari kelas yang mengimplementasikan __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, ketika menguji variabel dengan cara berikut, ekstra sadar tentang apa yang Anda termasuk atau tidak termasuk dari tes:

def some_function(value=None):
    if not value:
        value = init_value()

Di atas, apakah Anda bermaksud menelepon init_value() ketika nilai ditetapkan khusus untuk None, atau apakah maksud Anda bahwa nilai ditetapkan 0, atau string kosong, atau daftar kosong juga harus memicu inisialisasi. Seperti saya katakan, berhati-hatilah. Seperti yang sering terjadi pada Python eksplisit lebih baik daripada implisit.

None dalam praktek

None digunakan sebagai nilai sinyal

None memiliki status khusus dengan Python. Ini adalah nilai dasar favorit karena banyak algoritme memperlakukannya sebagai nilai luar biasa. Dalam skenario seperti itu dapat digunakan sebagai tanda untuk menandai bahwa suatu kondisi memerlukan penanganan khusus (seperti pengaturan nilai default).

Anda dapat menetapkan None ke argumen kata kunci dari suatu fungsi dan kemudian secara eksplisit menguji untuk itu.

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 menguji untuk itu sebelum melakukan sesuatu yang istimewa.

value = getattr(some_obj, 'some_attribute', None)
if value is None:
    # do something spectacular!

Secara default, kamus get() metode kembali None ketika mencoba mengakses kunci yang tidak ada:

>>> some_dict = {}
>>> value = some_dict.get('foo')
>>> value is None
True

Jika Anda mencoba untuk mengaksesnya dengan menggunakan notasi subscript a KeyError akan dibangkitkan

>>> value = some_dict['foo']
KeyError: 'foo'

Demikian juga jika Anda mencoba untuk mem-pop 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 dari None berlaku ketika tidak dianggap sebagai nilai yang valid, tetapi lebih seperti sinyal untuk melakukan sesuatu yang istimewa. Namun ada situasi di mana terkadang penting untuk mengetahui di mana None berasal dari karena meskipun digunakan sebagai sinyal itu juga bisa menjadi bagian dari data.

Saat Anda mengajukan kueri suatu objek untuk atributnya getattr(some_obj, 'attribute_name', None) mendapatkan kembali None tidak memberi tahu Anda apakah atribut yang Anda coba akses sudah diatur None atau jika itu sama sekali tidak ada dari objek. Situasi yang sama ketika mengakses kunci dari kamus seperti some_dict.get('some_key'), kamu tidak tahu jika some_dict['some_key'] hilang atau jika sudah diatur None. Jika Anda memerlukan informasi itu, cara biasa untuk menangani ini adalah secara langsung mencoba mengakses atribut atau kunci dari dalam a try/except membangun:

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 asterisks 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 di atas try/except pola hanya untuk membedakan antara None bendera dan None data, lalu gunakan nilai tes lain. Ada pola di mana nilai yang berada di luar kumpulan nilai yang valid disisipkan sebagai bagian dari data dalam struktur data dan digunakan untuk mengontrol dan menguji kondisi khusus (misalnya batas, negara, dll). Nilai seperti itu disebut a penjaga dan itu bisa digunakan None digunakan sebagai sinyal. Ini sepele untuk membuat sentinel dengan Python.

undefined = object()

Itu undefined objek di atas adalah unik dan tidak melakukan banyak hal yang mungkin menarik untuk program, sehingga merupakan pengganti yang sangat baik untuk None sebagai bendera. Beberapa peringatan berlaku, lebih lanjut tentang 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 dict

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 objek

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, para penjaga adat datang dengan beberapa peringatan. Pertama, mereka bukan kata kunci seperti None, jadi python tidak melindungi mereka. Anda dapat menimpa Anda undefined di atas kapan saja, di mana saja dalam modul yang ditentukan, jadi berhati-hatilah bagaimana Anda mengekspos dan menggunakannya. Selanjutnya, instance dikembalikan oleh object() bukan tunggal, jika Anda membuat panggilan itu 10 kali Anda mendapatkan 10 objek yang berbeda. Akhirnya, penggunaan sentinel sangat idiosynkratik. Sentinel adalah khusus untuk perpustakaan yang digunakan dalam dan karena itu ruang lingkupnya umumnya harus terbatas pada internal perpustakaan. Seharusnya tidak "bocor" keluar. Kode eksternal hanya harus menyadarinya, jika tujuannya adalah untuk memperpanjang atau melengkapi API perpustakaan.


26
2018-01-29 15:34



Per Uji nilai kebenaran, 'Tidak ada' langsung tes sebagai FALSE, sehingga ungkapan paling sederhana akan cukup:

if not foo:

0
2017-09-24 23:15