2012-08-07 13 views
5

Jaki jest najbardziej naturalny sposób wypełnienia poniższego kodu?Jak obsługiwać typy mieszane podczas wdrażania operatorów porównania?

import functools 

@functools.total_ordering 
class X: 
    def __init__(self, a): 
     self._a = a 

    def __eq__(self, other): 
     if not isinstance(other, X): 
      return False 
     return self._a == other._a 

    def __lt__(self, other): 
     if not isinstance(other, X): 
      return ...     // what should go here? 
     return self._a < other._a 

if __name__ == '__main__': 
    s = [2, 'foo', X(2)] 
    s.sort() 
    print s 

Odpowiedz

2

Możesz wybrać to, co wydaje ci się naturalne; False oznacza, że ​​Twoje instancje zawsze sortują według innych typów, True i zostaną posortowane wcześniej.

Alternatywnie, można powrócić NotImplemented (patrz the __lt__ and other comparison methods documentation) sygnalizować porównanie nie jest obsługiwany:

def __lt__(self, other): 
    if not isinstance(other, X): 
     return NotImplemented 
    return self._a < other._a 

Cytowanie dokumentację:

Bogaty metoda porównanie może zwrócić pojedyncza NotImplemented jeśli to nie implementuje operacji dla danej pary argumentów. Zgodnie z konwencją dla pomyślnego porównania zwracane są: False i True. Jednak te metody mogą zwracać dowolną wartość, więc jeśli operator porównania jest używany w kontekście logicznym (np. W warunku instrukcji if), Python wywoła bool() na wartości, aby określić, czy wynik jest prawdziwy czy fałszywy.

+1

Tylko powrót Fałsz lub Prawda nie jest dobrym pomysłem. Rozważmy przypadek, gdy masz inną analogiczną klasę Y i wykonaj X ("foo") X ("foo"). Wyniki mogą nie być spójne. – user763305

+1

Powraca jednak funkcja Nieudamierzone. Następnie Python użyje swojej własnej domyślnej kolejności, która jest nieco arbitralna, ale spójna. – user763305

4

Moje osobiste podejście:

wyjątek.

Nie ma naturalnego porządku między różnymi typami.

Oficjalna jeden: (wybrać ten jeden, nie powinno być)

Chociaż nie zgadzam się z tym całkowicie, instrukcja wyraźnie stwierdza, w jaki sposób należy to zrobić:

http://docs.python.org/library/stdtypes.html#comparisons

Obiekty różnych typów, z wyjątkiem różnych typów numerycznych i różnych typów ciągów, nigdy nie porównuj równych; takie obiekty są uporządkowane zgodnie z indywidualnymi, ale arbitralnie (tak, że sortowanie heterogenicznej tablicy daje spójny wynik). Ponadto niektóre typy (na przykład obiekty zbiorów ) obsługują tylko zdegenerowane pojęcie porównania, w którym dowolne obiekty tego typu są nierówne. Ponownie, takie obiekty są porządkowane, ale konsekwentnie. Operatory <, < =,> i> = podniosą wyjątek TypeError, gdy dowolny operand będzie liczbą zespoloną.

W zasadzie ... chciałbym podnieść wyjątek, ale najbardziej pytonowym sposobem wykonania zamówienia byłoby zastosowanie się do instrukcji.

Powinien istnieć jeden - a najlepiej tylko jeden - czysty sposób na zrobienie tego.

+0

Ale Python realizuje takie zamówienie. Mogę sortować listę [2.3, "foo", int]. – user763305

+0

'1> 'string'' jest fałszywe,' 1 <' string'' jest prawdziwe. –

+0

W szczególności 'TypeError (" nie może porównywać {} do {} ".format (typ (self), type (other)))'. – ecatmur

Powiązane problemy