Yok değeri nedir?


130

Python üzerinde çalışıyorum ve Nonedeğerini açıklayan bir bölüm okudum , ancak maalesef bu kitap bazı noktalarda çok net değil. Orada paylaşırsam sorumun cevabını bulacağımı düşündüm.

NoneDeğerin ne olduğunu ve onu ne için kullandığınızı bilmek istiyorum.

Ayrıca kitabın bu kısmını anlamadım:

NoneBir değişkene bir değer atamak , onu orijinal, boş durumuna sıfırlamanın bir yoludur.

Bu ne anlama geliyor?

Cevaplar harikaydı, ancak bilgisayar dünyasına ilişkin az bilgim nedeniyle çoğu cevabı anlamamama rağmen (dersler, nesneler vb. Hakkında bir şeyler öğrenmedim). Bu cümle ne anlama geliyor?

NoneBir değişkene bir değer atamak , onu orijinal, boş durumuna sıfırlamanın bir yoludur.

Final:

Sonunda cevabımı farklı cevaplara bakarak aldım. Bana yardım etmek için zaman ayıran herkesi takdir etmeliyim (özellikle Martijn Pieters ve DSM) ve tüm cevapları en iyi olarak seçebilmeyi diliyorum, ancak seçim bir ile sınırlı. Tüm cevaplar harikaydı.


39
Bu kitap pek yardımcı olmuyor; Nonedeğişkenler için varsayılan boş bir durum değildir.
Martijn Pieters

Başımın üstünde php, boş değeri bir değişken için varsayılan boş durumuna eşdeğer olan tek dildir. Şimdi başka hangi dillerin bunu yaptığını merak ediyorum.
kojiro

@kojiro perl, ancak eşitlik operatörlerinden hiçbiri ile karşılaştırmaktan memnun değil undef. ayrıca tartışmalı bir şekilde javascript, ancak hem nullve undefined.
Eevee

@kojiro javascript değişkeninin varsayılan değeri undefined, eğer başlatılmamışsa bırakılır.
thefourtheye

Olan sağ farklı dan nullben onun cevabını @MartijnPieters yapmak için başarısız olduğum bir noktadan.
kojiro

Yanıtlar:


99

Martijn'in cevabı NonePython'da ne olduğunu açıklar ve kitabın yanıltıcı olduğunu doğru bir şekilde belirtir. Python programcıları kural olarak asla

NoneBir değişkene bir değer atamak , onu orijinal, boş durumuna sıfırlamanın bir yoludur.

Briggs'in ne anlama geldiğini mantıklı ve buradaki hiç kimsenin neden bundan memnun olmadığını açıklayan bir şekilde açıklamak zor. Yardımcı olabilecek bir benzetme:

Python'da değişken isimler, nesnelere yapıştırılan çıkartmalar gibidir. Her çıkartmanın üzerinde yazılı benzersiz bir isim vardır ve bir seferde yalnızca bir nesne üzerinde olabilir, ancak isterseniz aynı nesneye birden fazla çıkartma koyabilirsiniz. Yazarken

F = "fork"

"F" etiketini bir string nesnesine koyarsınız "fork". Eğer yazarsan

F = None

çıkartmayı Nonenesneye taşırsınız.

Ne Briggs hayal etmek size soruyor sen vermedi olmasıdır yazma etiketi "F", orada zaten bir Fçıkartmadadır Noneve hem bütün olarak hareket dan, bunu Noneiçin "fork". Yani yazdığınızda F = None, Noneanlam olarak ele almaya karar verirsek, "orijinal, boş durumuna sıfırlarsınız" empty state.

Neye yaklaştığını görebiliyorum, ama bu kötü bir bakış açısı. Python'u başlatıp print(F)yazarsanız, şunu görürsünüz:

>>> print(F)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'F' is not defined

ve bu NameError, Python'un adı tanımadığı anlamına gelir F, çünkü böyle bir etiket yoktur . Briggs haklıysa ve orijinal durumuna F = Nonegeri dönerse F, o zaman şimdi orada olmalı ve görmeliyiz

>>> print(F)
None

F = NoneYazıp etiketi yapıştırdıktan sonra yaptığımız gibi None.


Yani tüm bunlar oluyor. Gerçekte, Python nesnelere zaten yapıştırılmış bazı çıkartmalarla birlikte gelir (yerleşik isimler), ancak diğerlerinde kendinizi F = "fork"ve A = 2ve gibi satırlarla yazmanız gerekir c17 = 3.14ve daha sonra bunları diğer nesnelere yapıştırabilirsiniz ( F = 10veya F = None; hepsi aynı .)

Briggs, yazmak isteyebileceğiniz tüm olası çıkartmaların Nonenesneye zaten yapıştırılmış olduğunu iddia ediyor .


1
pardon ama Briggs ile ne demek istiyorsun? Bu kitabın yazarından mı bahsediyorsun? çünkü adı Jason R. Briggs.
The_Diver

@The_Diver: evet, bu o.
DSM

Python'un yerleşik isimleri hakkında daha fazla bilgiyi nerede bulabilirim?
The_Diver

3
Bu, programcı olmayan biri için harika bir açıklamadır. Çok teşekkür ederim!
Christina

67

Nonesadece 'boş' veya 'burada değer yok' anlamına gelen bir değerdir. Bir sinyal nesnesidir ; sadece anlamı vardır, çünkü Python belgeleri bu anlama sahip olduğunu söyler.

Belirli bir Python yorumlayıcı oturumunda bu nesnenin yalnızca bir kopyası vardır.

Örneğin bir işlev yazarsanız ve bu işlev açık bir returnifade kullanmazsa , Nonebunun yerine döndürülür. Bu şekilde, işlevlerle programlama çok basitleştirilmiştir; bir işlev , yalnızca bir nesne olsa bile her zaman bir şey döndürür None.

Bunu açıkça test edebilirsiniz:

if foo is None:
    # foo is set to None

if bar is not None:
    # bar is set to something *other* than None

Diğer bir kullanım, isteğe bağlı parametrelere işlevlere 'boş' bir varsayılan vermektir:

def spam(foo=None):
    if foo is not None:
        # foo was specified, do something clever!

Fonksiyonun spam()isteğe bağlı bir argümanı vardır; spam()Bunu belirtmeden çağırırsanız , varsayılan değer Noneona verilir, bu da işlevin bir bağımsız değişkenle çağrılıp çağrılmadığını tespit etmeyi kolaylaştırır.

Diğer dillerin benzer kavramları vardır. SQL'de NULL; JavaScript, undefined ve null vb.

Python'da, değişkenler kullanıldıkları için var olur. Önce bir değişken tanımlamanıza gerek yoktur, bu yüzden Python'da gerçekten boş değişkenler yoktur . Bir değişkeni Noneolarak ayarlamak, onu varsayılan boş bir değere ayarlamakla aynı şey değildir; boşluğu işaretNone etmek için sıklıkla kullanılsa da, aynı zamanda bir değerdir . Okuduğunuz kitap bu noktada yanıltıcıdır.


1
Boşluğun anlambiliminin tanımsızlıktan farklı olduğunu düşünüyorum . Bu yüzden JavaScript ve SQL muadillerinin açıklığa kavuşturduğundan emin değilim - sorunu karıştırabilirler. JavaScript hem undefined ve hem de null.
kojiro

@kojiro: undefinedJavaScript'te bir nesnedir ve bu nesneyi NonePython'da kullanabildiğiniz gibi açıkça kullanabilirsiniz . Bu, hemen hemen aynı anlama sahip bir sinyal nesnesidir.
Martijn Pieters

@kojiro: SQL bir programlama dili değildir, ancak NULLyine de açıkça atanabilen ve test edilebilen bir şeydir.
Martijn Pieters

5
@MartijnPieters: SQL olan bir programlama dili, sadece çok özel amaç, bildirim biri.
danielkza

3
@daniel: SQL bir programlama dili olarak nitelendiriliyor uzun bir tartışma oldu ... İlginç açılar için stackoverflow.com/questions/900055/… sayfasına bakın .
Martijn Pieters

23

Python dokümantasyonunun söylediği şey şudur None:

Türlerin tek değeri.NoneType. Yok, varsayılan bağımsız değişkenler bir işleve iletilmediğinde olduğu gibi, bir değerin yokluğunu temsil etmek için sıklıkla kullanılır.

Sürüm 2.4'te değiştirildi: Yok'a atamalar yasa dışıdır ve bir SyntaxError oluşturur.

Not Yok adları ve hata ayıklama yeniden atanamaz (bunlara atamalar, bir öznitelik adı olarak bile SyntaxError değerini yükseltir), bu nedenle bunlar "doğru" sabitler olarak kabul edilebilir.

  1. Noneİlk türünü onaylayalım

    print type(None)
    print None.__class__

    Çıktı

    <type 'NoneType'>
    <type 'NoneType'>

Temelde, NoneTypetıpkı bir veri türüdür int, floatvb You Python bulunan varsayılan türlerinin listesini kontrol edebilirsiniz 8,15. türler - Yerleşik türler için adlar .

  1. Ve Nonebir NoneTypesınıf örneğidir . Bu yüzden Nonekendimizin örneklerini yaratmak isteyebiliriz . Hadi deneyelim

    print types.IntType()
    print types.NoneType()

    Çıktı

    0
    TypeError: cannot create 'NoneType' instances

Açıkça, NoneTypeörnekler oluşturamaz . Değerin benzersizliği konusunda endişelenmemize gerek yok None.

  1. NoneDahili olarak nasıl uyguladığımızı kontrol edelim .

    print dir(None)

    Çıktı

    ['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', 
     '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__',
     '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

Bunun dışında __setattr__tüm diğerleri salt okunur özniteliklerdir. Yani, niteliklerini değiştirebilmemizin bir yolu yok None.

  1. Deneyelim ve yeni özellikler eklemeye çalışalım None

    setattr(types.NoneType, 'somefield', 'somevalue')
    setattr(None, 'somefield', 'somevalue')
    None.somefield = 'somevalue'

    Çıktı

    TypeError: can't set attributes of built-in/extension type 'NoneType'
    AttributeError: 'NoneType' object has no attribute 'somefield'
    AttributeError: 'NoneType' object has no attribute 'somefield'

Yukarıda görülen ifadeler sırasıyla bu hata mesajlarını üretir. Bu, bir Noneörnekte dinamik olarak nitelikler oluşturamayacağımız anlamına gelir .

  1. Bir şey atadığımızda ne olacağını kontrol edelim None. Belgelere göre, bir SyntaxError. Bu, bir şey atarsak Noneprogramın hiç çalıştırılmayacağı anlamına gelir .

    None = 1

    Çıktı

    SyntaxError: cannot assign to None

Biz kurduk

  1. None bir örneği NoneType
  2. None yeni niteliklere sahip olamaz
  3. Öğesinin mevcut öznitelikleri Nonedeğiştirilemez.
  4. Diğer örneklerini oluşturamayız NoneType
  5. Referansı ona Nonedeğer atayarak bile değiştiremeyiz .

Bu nedenle, belgelerde belirtildiği gibi None, gerçekten bir true constant.

Mutlu bilmek None:)


Çok çok ilginç !! __setattr__Yok için ne
işe yaradığına

9

Bahsettiğiniz kitap açıkça anlamını büyük ölçüde basitleştirmeye çalışıyor None. Python değişkenleri yok olması bir ilk, boş devlet - Python değişkenleri olan tanımlandıkları yaparken (yalnızca) bağlı . Bir değer vermeden bir Python değişkeni oluşturamazsınız.

>>> print(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
>>> def test(x):
...   print(x)
... 
>>> test()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: test() takes exactly 1 argument (0 given)
>>> def test():
...   print(x)
... 
>>> test()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in test
NameError: global name 'x' is not defined

ancak bazen bir değişkenin tanımlanıp tanımlanmamasına bağlı olarak bir fonksiyonun farklı şeyler ifade etmesini istersiniz. Varsayılan değeri olan bir argüman oluşturabilirsiniz None:

>>> def test(x=None):
...   if x is None:
...     print('no x here')
...   else:
...     print(x)
... 
>>> test()
no x here
>>> test('x!')
x!

Bu değerin özel Nonedeğer olması bu durumda çok önemli değildir. Herhangi bir varsayılan değeri kullanabilirdim:

>>> def test(x=-1):
...   if x == -1:
...     print('no x here')
...   else:
...     print(x)
... 
>>> test()
no x here
>>> test('x!')
x!

… Ama Noneetrafta olmak bize iki fayda sağlar:

  1. -1Kimin anlamı net değil gibi özel bir değer seçmemize gerek yok ve
  2. Fonksiyonumuzun aslında -1normal bir girdi olarak ele alınması gerekebilir .
>>> test(-1)
no x here

ayy!

Dolayısıyla kitap, çoğunlukla reset kelimesini kullanımında biraz yanıltıcıdır - Nonebir isme atamak , bir programcıya bu değerin kullanılmadığını veya fonksiyonun varsayılan bir şekilde davranması gerektiğini, ancak bir değeri sıfırlamak için bir sinyaldir. orijinal, tanımsız durumuna kadar delanahtar kelimeyi kullanmanız gerekir :

>>> x = 3
>>> x
3
>>> del x
>>> x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined

5

Diğer cevaplar zaten anlam açıkladık Yok güzelce. Ancak yine de bir örnekle bu konuya daha fazla ışık tutmak isterim.

Misal:

def extendList(val, list=[]):
    list.append(val)
    return list

list1 = extendList(10)
list2 = extendList(123,[])
list3 = extendList('a')

print "list1 = %s" % list1
print "list2 = %s" % list2
print "list3 = %s" % list3

Şimdi yukarıdaki listenin çıktısını tahmin etmeye çalışın. Eh, cevap olarak aşağıda şaşırtıcı geçerli:

list1 = [10, 'a']
list2 = [123]
list3 = [10, 'a']

Ama neden?

Birçok yanlışlıkla bekliyoruz list1 eşit olacak şekilde [10] ve Liste3 eşit olacak şekilde [ 'a'] , liste argümanı ait varsayılan değerine ayarlanacak olduğunu düşünen [] extendList denir her seferinde.

Ancak, gerçekte olan şey, yeni varsayılan listenin işlev tanımlandığında yalnızca bir kez oluşturulması ve aynı listenin daha sonra bir liste bağımsız değişkeni belirtilmeden extList çağrıldığında daha sonra kullanılmasıdır. Bunun nedeni , varsayılan bağımsız değişkenlerdeki ifadelerin işlev çağrıldığında değil, işlev tanımlandığında hesaplanmasıdır .

Bu nedenle list1 ve list3 aynı varsayılan liste üzerinde çalışırken, liste2 kendi oluşturduğu ayrı bir liste üzerinde çalışır (liste parametresi için değer olarak kendi boş listesini ileterek).


Kurtarıcı 'Yok': (İstenen davranışı üretmek için yukarıdaki örneği değiştirin)

def extendList(val, list=None):
    if list is None:
       list = []
    list.append(val)
    return list

list1 = extendList(10)
list2 = extendList(123,[])
list3 = extendList('a')

print "list1 = %s" % list1
print "list2 = %s" % list2
print "list3 = %s" % list3

Bu gözden geçirilmiş uygulama ile çıktı:

list1 = [10]
list2 = [123]
list3 = ['a']

Not - toptal.com'a örnek kredi


3

Hiçbiri, dil ve kitaplığın pek çok yerinde başka bir değerin yokluğunu temsil etmek için kullanılan tek bir nesnedir (yani yalnızca bir Yok vardır).


Örneğin:
eğer dbir sözlük olduğunu d.get(k)dönecektir d[k]varsa, ancak Noneeğer dhiçbir anahtara sahip k.

Bu bilgiyi harika bir blogdan okuyun: http://python-history.blogspot.in/


3

Bunların hepsi iyi cevaplar ama bence neden Noneyararlı olduğunu açıklayacak daha çok şey var .

Bir düğün için LCV'leri topladığınızı hayal edin. Her kişinin katılıp katılmayacağını kaydetmek istiyorsunuz. Katılıyorlarsa, ayarlayın person.attending = True. Katılmıyorlarsa ayarlayın person.attending = False. Herhangi bir LCV almadıysanız, o zaman person.attending = None. Bu şekilde bilgi yok - None- ve olumsuz cevap arasında ayrım yapabilirsiniz .


1

Kod örneklerini (meyvelerin yanı sıra) seviyorum, bu yüzden size göstereyim

apple = "apple"
print(apple)
>>> apple
apple = None
print(apple)
>>> None

Hiçbiri hiçbir şey ifade etmez, değeri yoktur.

Hiçbiri False olarak değerlendirilmez.


8
print(None)baskılar .. None. It does not sen, baskı hiçbir şey önerdiği gibi.
Martijn Pieters

REPL yalnızca Noneson ifadenin sonucuysa hiçbir şey göstermez . (çoğunlukla bir değer döndürmeyi amaçlamayan işlevler için yararlıdır.)
Eevee

Eugh, benim hatam, IDLE kullanıyordum ve değişkenleri yazdırdığını varsaydım, görünüşe göre repl kullanıyor. Şu anda kendi python / javascript / kod okuma ve anlama becerilerimi mükemmelleştirmek için SO kullanıyorum, bu yüzden bazı hatalar yapıyorum :(
Azeirah

2
IDLE, Python etkileşimli yorumlayıcı istemi gibi, bunun bir ifadenin sonucu olup olmadığını, çoğunlukla çıktıyı karıştırmamak için açıkça gizler None .
Martijn Pieters

-5
largest=none
smallest =none 
While True :
          num =raw_input ('enter a number ') 
          if num =="done ": break 
          try :
           inp =int (inp) 
          except:
              Print'Invalid input' 
           if largest is none :
               largest=inp
           elif inp>largest:
                largest =none 
           print 'maximum', largest

          if smallest is none:
               smallest =none
          elif inp<smallest :
               smallest =inp
          print 'minimum', smallest 

print 'maximum, minimum, largest, smallest 
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.