2011-08-05 17 views
6

Mam słownika następującą postać:pyton równoważne porównywalnych

{ <Category('Simulate', 'False', 'False', 'False', 'INTERMEDIATE')>: {'link': u'/story/4/tvb-adapters-simulator-simulatorAdapter/SimulatorAdapter', 'name': u'Simulate'}, 
    <Category('View Results', 'True', 'False', 'True', 'INTERMEDIATE')>: {'link': '/story/step/3', 'name': u'View Results'}, 
    <Category('Analyze', 'True', 'False', 'False', 'FINAL')>: {'link': '/story/step/2', 'name': u'Analyze'}} 

kategoria jest klasa reprezentująca instancję z bazy danych. Teraz mam następujący przykład:

<Category('Analyze', 'True', 'False', 'False', 'FINAL')> 

To nie jest to samo wystąpienie. Rozumiem przez to, że otrzymuję wszystkie wartości z bazy danych i tworzę słownik. Następnie po pewnym czasie otrzymuję identyfikator i pobieraję instancję z bazy danych. Teraz nie są to te same obiekty. Teraz muszę sprawdzić, czy jest w słowniku, ale:

instance in disctionary 

Zwróci wartość false. Teraz mogłem przejść brzydki sposób i powtórzyć słownik, sprawdzając, czy wszystkie wartości są zgodne, jednak czy Python ma bardziej sprytny sposób na zrobienie tego? Mam na myśli coś podobnego do porównywalnego w Javie?

+1

ja nie uznają tego jako ważny Pythona. Co to jest ""? –

+2

To jest jego ładny drukowany dyktat i zwyczajowo używać nawiasów ostrych w klasie repr(). – pyroscope

+0

@pyroscope: Dzięki! Nauka czegoś nowego każdego dnia ... –

Odpowiedz

9

Po pierwsze: użyj True i False (właściwości boolowskie) zamiast 'True' i 'False' (właściwości łańcuchów).

Ogólnie rzecz biorąc, można uczynić wszystko porównywalnym w języku Python. Musisz tylko zdefiniować konkretne metody (takie jak __eq__, __lt__ itd.) Dla swojej klasy.

Więc powiedzmy, że chcę porównać instancje klasy A, a porównanie powinno być tylko wielkość liter porównanie ciąg s członka:

class A(object): 
    def __init__(self, s=''): 
     self.s = s 

    def __eq__(self, other): 
     return self.s.lower() == other.s.lower() 

a = A('aaaa') 
b = A('AAAA') 
print a == b # prints True 
b = A('bbbb') 
print a == b # prints False 
+0

Dziękujemy za dane wejściowe. To było to, czego szukałem. – Bogdan

2

zamiast używania wystąpień Category (np Category('Analyze', 'True', 'False', 'False', 'FINAL')) jako klucze w swoim słowniku, brzmi jak należy używać skojarzony krotki (np ('Analyze', 'True', 'False', 'False', 'FINAL')).

Jeśli naprawdę chcesz użyć instancji Category jako kluczy w słowniku, musisz zdefiniować metody __hash__ i __eq__. Na przykład:

class Category(object): 
    def __init__(self,*args): 
     self.args=args 
    def __hash__(self): 
     # Note that this assumes that Category's hash value is immutable 
     # i.e. self.args does not change. 
     return hash(self.args) 
    def __eq__(self,other): 
     return self.args == other.args 

a=Category('Analyze', 'True', 'False', 'False', 'FINAL') 
b=Category('Analyze', 'True', 'False', 'False', 'FINAL') 

mydict={a:1} 

a i b są różne przypadki, tak, że mają różne id S, lecz ich wartości hash są takie same:

assert id(a) != id(b) 
assert hash(a)==hash(b) 

Pokazuje b jest dopuszczalne kluczem mydict:

print(mydict[a]) 
# 1 
print(mydict[b]) 
# 1 

PS. Nie przejmuj się __cmp__. In Python 3:

Funkcja CMP() powinny być traktowane jako nie ma, a szczególny sposób __cmp__() nie jest obsługiwany. W razie potrzeby użyj __lt__() do sortowania, a następnie innych szczegółowych porównań.

+0

Używam krotek, które były wynikiem drukowania preety. – Bogdan

1

Nie może być skróty, jak przy użyciu krotki, ale odpowiedź na pytanie rodzajowy jest: wdrożenie __eq__() dla swojej klasie, dzięki czemu cmp() będzie go używać zamiast testowania tożsamości.

1

Dla in i innych operatorów porównania do pracy, masz implementować __hash__ i __cmp__ (lub "bogate" metody porównywania, takie jak __eq__). Zobacz Python reference.

1

Ponieważ najwyraźniej możesz umieścić swoje instancje kategorii w dyktafonie, musisz już nadpisać __hash__. Wszystko, co musisz teraz jest __eq__:

class Category(object): 
    # you must have overwritten `__hash__` like this already 
    def __hash__(self): 
     return hash((self.attr1, self.attr2, ...)) 

    # now you just need tis 
    def __eq__(self, other): 
     return isinstance(other, Category) and \ 
       (self.attr1, self.attr2, ...) == (other.attr1, other.attr2, ...) 

Co należy zrobić, to rzucić naprawdę to cała klasa się i używać collections.namedtuple zamiast:

Category = collections.namedtuple('Category', 'attr1 attr2 attr3') 
+0

+1 dla collections.namedtuple. – user9876