Dans quelles circonstances sont __rmul__ appelés?
Dire que j'ai une liste l
. Dans quelles circonstances est l.__rmul__(self, other)
appelé?
En gros, j'ai compris la documentation, mais j'aimerais aussi voir un exemple pour clarifier ses usages au-delà de tout doute.
Vous devez vous connecter pour publier un commentaire.
Quand Python tente de multiplier deux objets, il tente d'abord d'appeler la gauche de l'objet
__mul__()
méthode. Si l'objet de gauche, n'ont pas de__mul__()
de la méthode (ou la méthode renvoieNotImplemented
, indiquant qu'il ne fonctionne pas avec l'opérande de droite en question), puis Python veut savoir si le droit de l'objet peut faire la multiplication. Si l'opérande de droite est du même type que la gauche, Python sait qu'il ne peut pas, parce que si l'objet de gauche ne peut pas le faire, un autre objet du même type ne peut certainement pas non plus.Si les deux objets sont de types différents, bien que, Python chiffres, il est vaut le coup. Cependant, il a besoin d'une façon de dire à la droite de l'objet qu'il est le droit de l'objet de l'opération, dans le cas où l'opération n'est pas commutative. (La Multiplication est, bien sûr, mais pas tous les opérateurs, et en tout cas
*
n'est pas toujours utilisé pour la multiplication!) Donc il appelle__rmul__()
au lieu de__mul__()
.Considérez, par exemple, les deux instructions suivantes:
Dans le premier cas, Python appelle la chaîne du
__mul__()
méthode. La chaîne sait comment multiplier par un nombre entier, donc tout va bien. Dans le second cas, l'entier ne sait pas comment se multiplier en une chaîne de caractères, de sorte que son__mul()__
retourneNotImplemented
et de la chaîne__rmul()__
est appelé. Il sait quoi faire, et vous obtenez le même résultat que le premier cas.Maintenant, nous pouvons voir que
__rmul()__
permet tous de la chaîne de caractères spéciaux multiplication comportement figurant dans lestr
de la classe, de telle sorte que les autres types (tels que les entiers) n'ont pas besoin de savoir quelque chose au sujet de chaînes à être en mesure de multiplier par eux. Une centaine d'années à partir de maintenant (en supposant que Python est encore en usage), vous serez en mesure de définir un nouveau type qui peut être multipliée par un nombre entier dans l'ordre, même si leint
classe n'a rien connu d'elle depuis plus d'un siècle.Par ailleurs, la chaîne de la classe
__mul__()
a un bug dans certaines versions de Python. Si il ne sait pas comment se multiplier par un objet, il soulève unTypeError
au lieu de retournerNotImplemented
. Cela signifie que vous ne pouvez pas multiplier une chaîne de caractères par un type défini par l'utilisateur, même si le type défini par l'utilisateur dispose d'un__rmul__()
méthode, parce que la chaîne ne jamais lui permet d'avoir une chance. Le type défini par l'utilisateur doit passer en premier (par exempleFoo() * 'bar'
au lieu de'bar' * Foo()
) pour sa__mul__()
est appelé. Ils semblent avoir corrigé cela dans Python 2.7 (je l'ai testé en Python 3.2 également), mais Python 2.6.6 a le bug.Opérateurs binaires de par leur nature, les deux opérandes. Chaque opérande peut être soit sur la gauche ou du côté droit de l'opérateur. Lorsque vous la surcharge d'un opérateur pour un certain type, vous pouvez spécifier de quel côté de l'opérateur, la surcharge est fait. Ceci est utile lors de l'appel de l'opérateur sur les deux opérandes de types différents. Voici un exemple:
Ici,
obj
sera unBar
avecval = 24
, mais la cession deobj2
génère une erreur carBar
n'a pas de__mul__
etFoo
n'a pas de__rmul__
.J'espère que c'est assez clair.