2011-08-20 10 views
19

Napisałem klasę reprezentującą wektory w języku Python (jako ćwiczenie) i mam problemy z rozszerzeniem wbudowanych operatorów.Zdefiniowana przez użytkownika metoda __mul__ nie jest przemienna

Zdefiniowałem metodę __mul__ dla klasy wektorowej. Problem polega na tym, że w wyrażeniu x * y interpreter wywołuje metodę x, a nie y.

Tak vector(1, 2, 3) * 2 zwraca wektor < 2, 4, 6> tak jak powinien; ale 2 * vector(1, 2, 3) tworzy TypeError, ponieważ wbudowana klasa int nie obsługuje mnożenia przez moje zdefiniowane przez użytkownika wektory.

mogę rozwiązać ten problem, po prostu pisząc nową funkcję mnożenia

def multiply(a, b): 
    try: 
     return a * b 
    except TypeError: 
     return b * a 

ale wymagałoby to przedefiniowanie każdej funkcji, które chcę użyć z moich klas zdefiniowanych przez użytkownika.

Czy istnieje sposób, aby funkcja wbudowana obsługiwała to poprawnie?

Odpowiedz

24

Jeśli potrzebujesz komutacji dla różnych typów, musisz wdrożyć __rmul__(). Jeśli jest zaimplementowany, jest wywoływany, podobnie jak wszystkie metody specjalne __r*__(), jeśli operacja w przeciwnym razie podniosłaby wartość TypeError. Pamiętaj, że argumenty są zamienione:

class Foo(object): 
    def __mul_(self, other): 
     ''' multiply self with other, e.g. Foo() * 7 ''' 
    def __rmul__(self, other): 
     ''' multiply other with self, e.g. 7 * Foo() ''' 
+0

Jak Python wiedzieć, aby wywołać 'foo .__ rmul__' a nie' __mul__' z innego obiektu? –

+2

Próbuje użyć '__mul__' po lewej stronie, a jeśli nie może tego znaleźć, szuka' __rmul__' po prawej stronie. –

+3

@pst, Python najpierw wywołuje '__mul__', ale jeśli nie istnieje lub zwraca' NotImplemented', to Python wywołuje '__rmul__' innego obiektu. (Zauważ, że jeśli '__mul__' podnosi execption,' __rmul__' jest __not__ wywoływany. –

Powiązane problemy