“Foo is None” ile “foo == None” arasında herhangi bir fark var mı?


217

Arasında herhangi bir fark var mı:

if foo is None: pass

ve

if foo == None: pass

Çoğu Python kodunda (ve kendim yazdığım kod) gördüğüm kural eski, ama son zamanlarda ikincisini kullanan kodla karşılaştım. Hiçbiri, NoneType'ın bir örneği (ve tek örneği IIRC) değildir, bu yüzden önemli olmamalı, değil mi? Olabileceği herhangi bir durum var mı?

Yanıtlar:


253

isher zaman Trueaynı nesne örneğini karşılaştırırsa geri döner

Oysa ==sonunda belirlenir __eq__()yöntemi

yani


>>> class Foo(object):
       def __eq__(self, other):
           return True

>>> f = Foo()
>>> f == None
True
>>> f is None
False

51
Hiçbiri'nin bir tekton olduğunu ve "Hiçbiri Hiçbiri" nin her zaman Doğru olduğunu eklemek isteyebilirsiniz.
e-satis

43
Ayrıca, isoperatörün özelleştirilemeyeceğini (kullanıcı tanımlı bir sınıf tarafından aşırı yüklenmiş) eklemek isteyebilirsiniz .
martineau

@study Yöntem __eq__(self), ==bir Python nesnesinde kullanıldığında nasıl ele alınacağını belirleyen yerleşik bir yöntemdir . Burada onu geçersiz kıldık, böylece ==tür nesnelerde kullanıldığında Fooher zaman true değerini döndürür. isOperatör için eşdeğer bir yöntem yoktur ve dolayısıyla davranışı isaynı şekilde değiştirilemez.
Brendan

Foo sınıfının tanımının bir kurucu, yani init işlevi olmadığı için mi?
Çalışma

49

Bu nesne kimliğini ve denkliğini okumak isteyebilirsiniz .

'İs' ifadesi nesne kimliği için kullanılır, nesnelerin aynı örneğe (bellekteki aynı adrese) karşılık gelip gelmediğini kontrol eder.

Ve '==' ifadesi eşitlik anlamına gelir (aynı değer).


Hmmm, python'dan dış işlevleri nasıl arayacağınızla
Pat

Sadece denedim a=1;b=1;print(a is b) # True. a is b2 farklı nesne (bellekte farklı adres) gibi görünseler bile neden doğru oldukları konusunda bir fikriniz var mı?
Johnny Chiu

24

Uyarı kelimesi:

if foo:
  # do something

değil tam olarak aynı:

if x is not None:
  # do something

Birincisi bir boolean değer testidir ve farklı bağlamlarda false olarak değerlendirilebilir. Bir boolean değer testinde false değerini temsil eden bir takım şeyler vardır, örneğin boş kaplar, boolean değerleri. Hiçbiri bu durumda yanlış olarak değerlendirmez, ancak başka şeyler de yapar.


12

(ob1 is ob2) eşittir (id(ob1) == id(ob2))


6
... ama (ob, ob2) çok daha hızlı. Timeit "(a is b)" her döngü için 0.0365 usec ve "(id (a) == id (b))" her döngü için 0.153 usec diyor. 4.2x daha hızlı!
AKX

4
issürümü işlev çağrısı, ve hiçbir piton-tercüman nitelik araması gerekir; yorumcu ob1 aslında ob2 ise hemen cevap verebilir.
u0b34a0f6ae

17
Hayır. {} is {}yanlıştır ve id({}) == id({})olabilir (ve olduğu CPython olarak) doğru. Bkz. Stackoverflow.com/questions/3877230
Piotr Dobrogost

12

Bunun nedeni foo is Nonetercih edilen yol, kendi __eq__tanımlayan ve nesneyi Yok olarak tanımlayan bir nesneyi işlemiş olmanızdır . Yani, her zaman foo is Nonebunun infact olup olmadığını görmek için kullanın None.


8

Hiçbir fark yoktur, çünkü özdeş olan nesneler elbette eşit olacaktır. Bununla birlikte, PEP 8 açıkça kullanmanız gerektiğini belirtir is:

Hiçbiri gibi singletonlarla karşılaştırmalar daima eşitlik operatörleri ile yapılır veya yapılmaz.


7

iseşitlik için değil , kimlik için testler . İfadeniz için foo is nonePython basitçe nesnelerin hafıza adresini karşılaştırır. Bu, "Aynı nesne için iki ismim var mı?"

==diğer taraftan __eq__()yöntemle belirlenen eşitlik testleri . Kimliği umursamıyor.

In [102]: x, y, z = 2, 2, 2.0

In [103]: id(x), id(y), id(z)
Out[103]: (38641984, 38641984, 48420880)

In [104]: x is y
Out[104]: True

In [105]: x == y
Out[105]: True

In [106]: x is z
Out[106]: False

In [107]: x == z
Out[107]: True

Nonetekli bir operatördür. Bu None is Noneher zaman doğrudur.

In [101]: None is None
Out[101]: True

5

Hiçbiri için eşitlik (==) ve kimlik (is) arasında bir fark olmamalıdır. NoneType muhtemelen eşitlik için kimlik döndürür. Hiçbiri NoneType yapabileceğiniz tek örnek olduğundan (bu doğru olduğunu düşünüyorum), iki işlem aynıdır. Diğer tiplerde bu her zaman geçerli değildir. Örneğin:

list1 = [1, 2, 3]
list2 = [1, 2, 3]
if list1==list2: print "Equal"
if list1 is list2: print "Same"

Listelerde kimliğin varsayılan olarak döndürülmediği bir karşılaştırma işlemi bulunduğundan, "Eşit" yazdırılır.


5

@ Jason :

Daha fazla bir şey kullanmanızı tavsiye ederim

if foo:
    #foo isn't None
else:
    #foo is None

Foo gerçekten bir boolean değerini (yani 0 veya 1) temsil etmediği sürece "if foo:" kullanmayı sevmiyorum. Foo bir dize veya bir nesne veya başka bir şeyse, "if foo:" işe yarayabilir, ancak bana tembel bir kısayol gibi görünüyor. X'in None olup olmadığını kontrol ediyorsanız, "x None ise:" deyin.


Boş dizelerin / listelerin "if var" ile kontrol edilmesi tercih edilen yoldur. Boolean dönüşümü iyi tanımlanmıştır ve daha iyi performans gösteren daha az koddur. Örneğin "if len (mylist) == 0" yapmak için bir neden yok.
truppo

Yanlış. Foo = "" diyelim. Sonra if fooyanlış döndürür ve yorum #foo is Noneyanlış.
17'de blokeley

Downvoters için not - Cevabım, o zamandan beri silinmiş ve onunla aynı fikirde değilim. Eğer varsa yok cevabım kodu gibi yapmanız gerekenler upvote . :-)
Graeme Perrow

2

Bazı ayrıntılar:

  1. isFıkra aslında çekler iki eğer objectler aynı belleğe ya da değil altındadır. ikisinin de aynı bellek konumuna işaret edip etmediği ve aynı olup olmadığı id.

  2. 1'in bir sonucu olarak, issözlüksel olarak temsil edilen iki objects'nin aynı özniteliklere (öznitelik öznitelikleri ...) sahip olup olmamasını sağlar.

  3. Gibi temel türlerin Destekleme bool, int, string(bazı hariç), NoneTypebir aynı değere sahip olan, her zaman aynı belleğe olur.

Örneğin

>>> int(1) is int(1)
True
>>> str("abcd") is str("abcd")
True
>>> bool(1) is bool(2)
True
>>> bool(0) is bool(0)
True
>>> bool(0)
False
>>> bool(1)
True

Ve NoneTypepython'un "arama" tablosunda yalnızca bir örneği olabileceğinden, ilk ve sonuncusu, kodu yazan geliştiricinin (belki de tutarlılık için) daha ziyade herhangi bir ince mantıksal nedene sahip bir programlama stilidir. birini diğerinden seçin.


2
Bunu okuyan herkes: HİÇBİR some_string is "bar"dizeleri karşılaştırmak için KULLANMAYIN . Bunu yapmak için TEK BİR KABUL SEBEP DEĞİLDİR ve beklemediğinizde KIRILACAKTIR. Sıklıkla çalışması gerçeği, CPython'un aynı içeriğe sahip iki değişmez nesne oluşturmanın aptalca olacağını bilmesidir. Ancak yine de olabilir.
ThiefMaster

@ThiefMaster Cevabın yanlış yorumlanma eğilimi var mı? Gerçi, tekrar okumaya üzerine ben o ( "bazı istisnalar" bahsedilir) olmak bulamadık. İfadeniz sadece dizeler için geçerli int, değil mi?
Kanama Parmakları

Aslında değil, ama cevabınızda bu örneğe sahip olduğunuzdan, kullanıcıları gerçekten kullanmanın kötü bir fikir olduğu konusunda uyarmanın iyi bir fikir olacağını düşündüm. Belki bu satırın arkasına "# cpython özgü / garanti edilmez" gibi bir şey ekleyin ...
ThiefMaster

1

John Machin'in Nonesingleton olduğu sonucu, bu kodla desteklenen bir sonuçtur.

>>> x = None
>>> y = None
>>> x == y
True
>>> x is y
True
>>> 

Çünkü Nonebir single, x == Noneve x is Noneaynı sonucu olurdu. Ancak, estetik görüşüme göre x == None, en iyisi.


2
Bu cevabın sonunda görüşe katılmıyorum. Hiçbiri ile açıkça karşılaştırılmadığında, genellikle söz konusu nesnenin tam olarak nesne olması amaçlanır None. Karşılaştırma olarak, nadiren, Falsediğer değerlerin doğru olması dışında, başka hiçbir bağlamda kullanılan Yok'u görür . Bu gibi durumlarda böyle bir şey yapmak daha deyimseldirif x: pass
SingleNegationElimination

0
a is b # returns true if they a and b are true alias
a == b # returns true if they are true alias or they have values that are deemed equivalence 


a = [1,3,4]
b = a[:] #creating copy of list
a is b # if gives false
False
a == b # gives true
True
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.