2011-08-20 11 views
19

Ho scritto una classe per rappresentare i vettori in Python (come esercizio) e ho problemi con l'estensione degli operatori integrati.Il metodo __mul__ definito dall'utente non è commutativo

Ho definito un metodo __mul__ per la classe vector. Il problema è che nell'espressione x * y l'interprete chiama il metodo __mul__ di x, non y.

Quindi vector(1, 2, 3) * 2 restituisce un vettore < 2, 4, 6> proprio come dovrebbe; ma 2 * vector(1, 2, 3) crea un TypeError perché la classe int integrata non supporta la moltiplicazione dei miei vettori definiti dall'utente.

ho potuto risolvere questo problema scrivendo semplicemente una nuova funzione di moltiplicazione

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

ma ciò richiederebbe ridefinendo ogni funzione che voglio usare con i miei classi definite dall'utente.

C'è un modo per farlo funzionare correttamente?

risposta

24

Se si desidera commutatività per diversi tipi è necessario implementare __rmul__(). Se implementato, viene chiamato, come tutti i metodi speciali __r*__(), se l'operazione alza altrimenti un valore TypeError. Attenzione che gli argomenti sono invertiti:

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

Come fa sapere Python per invocare 'rmul__' Foo .__ e non il' __mul__' dell'altro oggetto? –

+2

Prova ad usare il "__mul__' sul lato sinistro, e se non riesce a trovarlo, cerca" __rmul__' sul lato destro. –

+3

@pst, Python chiama '__mul__' prima, ma se non esiste o se restituisce' NotImplemented', Python chiama '__rmul__' dell'altro oggetto. (Si noti che se '__mul__' solleva un execption,' __rmul__' è __not__ chiamato. –

2

Credo che siete alla ricerca di __rmul__