2010-06-19 13 views
19

Python yeniyim ve ben daha sonra ağrılı hatalara neden olmayacak şekilde, eğer doğru __eq__ ve __hash__ overrode emin olmak istedik: (. Ben Google App Engine kullanıyorum) Python: Bu, __eq__ ve __hash__'yi geçersiz kılmanın iyi bir yolu mu?

class Course(db.Model): 
    dept_code = db.StringProperty() 
    number = db.IntegerProperty() 
    title = db.StringProperty() 
    raw_pre_reqs = db.StringProperty(multiline=True) 
    original_description = db.StringProperty() 

    def getPreReqs(self): 
     return pickle.loads(str(self.raw_pre_reqs)) 

    def __repr__(self): 
     title_msg = self.title if self.title else "Untitled" 
     return "%s %s: %s" % (self.dept_code, self.number, title_msg) 

    def __attrs(self): 
     return (self.dept_code, self.number, self.title, self.raw_pre_reqs, self.original_description) 

    def __eq__(self, other): 
     return isinstance(other, Course) and self.__attrs() == other.__attrs() 

    def __hash__(self): 
     return hash(self.__attrs()) 

biraz daha karmaşık bir türü:

class DependencyArcTail(db.Model): 
    ''' A list of courses that is a pre-req for something else ''' 
    courses = db.ListProperty(db.Key) 

    ''' a list of heads that reference this one ''' 
    forwardLinks = db.ListProperty(db.Key) 

    def __repr__(self): 
     return "DepArcTail %d: courses='%s' forwardLinks='%s'" % (id(self), getReprOfKeys(self.courses), getIdOfKeys(self.forwardLinks)) 

    def __eq__(self, other): 
     if not isinstance(other, DependencyArcTail): 
      return False 

     for this_course in self.courses: 
      if not (this_course in other.courses): 
       return False 

     for other_course in other.courses: 
      if not (other_course in self.courses): 
       return False 

     return True 

    def __hash__(self): 
     return hash((tuple(self.courses), tuple(self.forwardLinks))) 

Her şey iyi görünüyor?

Güncellenen

Alex'in yorumların

class DependencyArcTail(db.Model): 
    ''' A list of courses that is a pre-req for something else ''' 
    courses = db.ListProperty(db.Key) 

    ''' a list of heads that reference this one ''' 
    forwardLinks = db.ListProperty(db.Key) 

    def __repr__(self): 
     return "DepArcTail %d: courses='%s' forwardLinks='%s'" % (id(self), getReprOfKeys(self.courses), getIdOfKeys(self.forwardLinks)) 

    def __eq__(self, other): 
     return isinstance(other, DependencyArcTail) and set(self.courses) == set(other.courses) and set(self.forwardLinks) == set(other.forwardLinks) 

    def __hash__(self): 
     return hash((tuple(self.courses), tuple(self.forwardLinks))) 

cevap

14

birincisi gayet @ yansıtmak için. Eşit fakat sahip farklı karmaları

ikinciyi düzeltmek istiyorum karşılaştırmak istiyorsunuz özdeş .courses ancak farklı .forwardLinks ile .courses

  • iki tarafın

    1. olabileceğini yinelenenler: ikincisi iki nedenden dolayı problemlidir Biri eşitlik yaparak hem kurslara hem de ileriye doğru bağlantılara bağlıdır, fakat her ikisi de kümelerdeki değişimlere (dolayısıyla çoğaltılmamış) ve aynı hashile göre değişir.

      def __eq__(self, other): 
          if not isinstance(other, DependencyArcTail): 
           return False 
      
          return (set(self.courses) == set(other.courses) and 
            set(self.forwardLinks) == set(other.forwardLinks)) 
      
      def __hash__(self): 
          return hash((frozenset(self.courses), frozenset(self.forwardLinks))) 
      

      Bu tabii ileriye bağlayan varsayarak olduğu, yani .: , bir nesnenin "gerçek değerine" açısından çok önemli vardır aksi halde __eq__ ve __hash__ hem çıkarılmalıdır.

      Düzenleme: (@ Mark [[tx !!!]] ile bir açıklama tarafından önerilen ve muhtemelen zarar verici) en iyi yedekli vardı tuple için __hash__ aramaları çıkarıldı; @Phillips [[tx !!!]] tarafından yapılan bir yorum tarafından önerildiği gibi, set - frozenset değerini hashleme olarak değiştirdi.

  • +0

    Güzel görünüyor. Teşekkürler. –

    +0

    @Rosarch, rica ederim! –

    +1

    @Alex: Bu, bir çeşit rasgele olabilecek tuple (set (self.courses)) öğesindeki öğelerin sırasına bağlı değil mi? –

    İlgili konular