2012-09-17 29 views
6

Aşağıdaki kod var:Operatör aşırı yüklerken python türleri mi değişir?

a = str('5') 
b = int(5) 
a == b 
# False 

Ama int bir alt sınıfı yaparsanız ve __cmp__ reimplement:

class A(int): 
    def __cmp__(self, other): 
     return super(A, self).__cmp__(other) 
a = str('5') 
b = A(5) 
a == b 
# TypeError: A.__cmp__(x,y) requires y to be a 'A', not a 'str' 

Neden bu iki farklı? Python çalışma zamanı, int.__cmp__() tarafından atılan TypeError'ı yakalayıp bunu False değeri olarak yorumluyor mu? Birisi bana bunun nasıl çalıştığını gösteren 2.x cpython kaynağında biraz işaret edebilir mi? Işleve wrap_cmpfunc yılında typeobject.c bu sonuca nedenini bulabilirsiniz CPython kaynağını 2.x için İlişkin

Güncelleme

>>> class A(int): 
...  def __cmp__(self, other): 
...   return super(A, self).__cmp__(A(other)) # <--- A(other) instead of other 
... 
>>> a = str('5') 
>>> b = A(5) 
>>> a == b 
True 

: Ben senin sorunun hakkını anlasalardı

+0

Bir yan notta: '__cmp__''nin yaşlardan önce kullanımdan kaldırıldığını biliyor musunuz? Zengin karşılaştırma işlevlerini uygulamanız gerekir. – Bakuriu

+0

Evet, bu, bir istisna yükseltmek mi, yoksa __eq__ uygulamasında NotImplemented mi döndüreceğimi anlamaya çalışırken ortaya çıktı. Yerleşik Python sınıflarının neler yaptığını görmek istedim ve tutarsız görünen bu örneği buldum. – Chris

cevap

5

belgeleri bu noktada tamamen açık değil, ama here bkz:

hem sayılar, ortak bir türe dönüştürülür varsa. Aksi takdirde, farklı türdeki nesneler her zaman eşitsiz bir şekilde karşılaştırır ve tutarlı bir şekilde ama keyfi olarak sıralanır. Özel yöntem adları bölümünde açıklanan __cmp__ yöntemini veya __gt__ gibi zengin karşılaştırma yöntemlerini tanımlayarak yerleşik olmayan türdeki nesnelerin karşılaştırma davranışını denetleyebilirsiniz.

(özellikle de "farklı türde nesneleri" arasında kesin bir kontrast "nesneleri olmayan yerleşik türleri") dahili için türleri, aslında çağrı karşılaştırma yöntemlerinin normal işlemi atlanır önermektedir: Eğer iki farklı (ve sayısal olmayan) yerleşik tipteki nesneleri karşılaştırmaya çalışırsınız, bu sadece otomatik bir False'ye kısa devre yapar.

-2

, gibi bir şey gerek aslında iki şeyi kontrol eder: verilen karşılaştırma işlevi func ve otherself için alt tiptir.

if (Py_TYPE(other)->tp_compare != func && 
    !PyType_IsSubtype(Py_TYPE(other), Py_TYPE(self))) { 
// .... 
} 
+3

Bunun hiç de soruyu ele aldığını sanmıyorum. OP, karşılaştırma çalışmasını yapmak için diğer türlerini zorlayabileceğini kabul eder. Soru şu ki * neden yapıyor? * Neden __cmp__' türlerin aynı olmadığını ve 'False 'hemen geri döndüğünü görmüyor? – mgilson

+4

Asıl soru, "str" ​​ve "int" kelimelerinin nasıl karşılaştırılacağı değil, iki farklı sonuç vardır. –

+0

Güncelleme yanıtı. –

3

a == b için bir karşılaştırma karar ağacı arar gibi bir şey:

  • piton aramalar a.__cmp__(b)
      b uygun bir tip b uygun bir tip ise
    • olduğunu
    • a çek, 0, -1 dönmek b veya +1
    • ise değil, -1, 0 veya +1, piton yapılır döndü NotImplented
  • eğer return; Aksi
  • NotImplented döndü eğer a uygun bir tip a uygun bir tip ise
  • olduğunu,
  • b.__cmp__(a)
    • b çek denemek değil -1, 0 veya +1
    • a eğer dönmek, geri dön NotImplemented
  • , -1, 0 veya +1 döndürülürse, python bitti; NotImplented tekrar döndü eğer aksi
  • , cevap False

değil tam cevabı, ama umarım yardımcı olur.

+0

Güzel olduğunu, ancak hata mesajını açıklamadığını. –

İlgili konular