什么情况下调用__rmul__?
假设我有一个列表l
。什么情况下会调用l.__rmul__(self, other)
?
我基本上理解了文档,但我还想看一个示例来毫无疑问地阐明其用法。
Say I have a list l
. Under what circumstance is l.__rmul__(self, other)
called?
I basically understood the documentation, but I would also like to see an example to clarify its usages beyond any doubt.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
当 Python 尝试将两个对象相乘时,它首先尝试调用左侧对象的 __mul__() 方法。如果左侧对象没有 __mul__() 方法(或者该方法返回
NotImplemented
,表明它不适用于相关的右侧操作数),则 Python想知道正确的对象是否可以进行乘法运算。如果右操作数与左操作数的类型相同,Python 就知道它不能,因为如果左操作数不能做到这一点,那么相同类型的另一个对象当然也不能。不过,如果这两个对象是不同的类型,Python 认为值得一试。然而,它需要某种方式来告诉正确的对象,它是操作中的正确对象,以防操作不可交换。 (当然,乘法是,但并非所有运算符都是,并且在任何情况下
*
并不总是用于乘法!)因此它调用__rmul__()
而不是__mul__()
。作为示例,请考虑以下两个语句:
在第一种情况下,Python 调用字符串的
__mul__()
方法。字符串知道如何将自身乘以一个整数,所以一切都很好。在第二种情况下,整数不知道如何将自身与字符串相乘,因此其__mul__()
返回NotImplemented
,而字符串的__rmul__()
返回代码 > 被调用。它知道要做什么,并且您会得到与第一种情况相同的结果。现在我们可以看到,__rmul__() 允许将字符串的所有特殊乘法行为包含在
str
类中,这样其他类型 (例如整数)不需要了解任何关于字符串的信息就可以与它们相乘。一百年后(假设 Python 仍在使用),您将能够定义一个可以按任意顺序乘以整数的新类型,即使int
类对此一无所知一个多世纪以来。顺便说一句,字符串类的
__mul__()
在某些版本的 Python 中存在错误。如果它不知道如何将自身与对象相乘,则会引发TypeError
而不是返回NotImplemented
。这意味着即使用户定义类型具有__rmul__()
方法,您也不能将字符串与用户定义类型相乘,因为字符串永远不会让它有机会。用户定义的类型必须先行(例如Foo() * 'bar'
而不是'bar' * Foo()
),因此它的__mul__()
被调用。他们似乎已经在 Python 2.7 中修复了这个问题(我也在 Python 3.2 中测试了它),但是 Python 2.6.6 有这个错误。When Python attempts to multiply two objects, it first tries to call the left object's
__mul__()
method. If the left object doesn't have a__mul__()
method (or the method returnsNotImplemented
, indicating it doesn't work with the right operand in question), then Python wants to know if the right object can do the multiplication. If the right operand is the same type as the left, Python knows it can't, because if the left object can't do it, another object of the same type certainly can't either.If the two objects are different types, though, Python figures it's worth a shot. However, it needs some way to tell the right object that it is the right object in the operation, in case the operation is not commutative. (Multiplication is, of course, but not all operators are, and in any case
*
is not always used for multiplication!) So it calls__rmul__()
instead of__mul__()
.As an example, consider the following two statements:
In the first case, Python calls the string's
__mul__()
method. The string knows how to multiply itself by an integer, so all is well. In the second case, the integer does not know how to multiply itself by a string, so its__mul__()
returnsNotImplemented
and the string's__rmul__()
is called. It knows what to do, and you get the same result as the first case.Now we can see that
__rmul__()
allows all of the string's special multiplication behavior to be contained in thestr
class, such that other types (such as integers) do not need to know anything about strings to be able to multiply by them. A hundred years from now (assuming Python is still in use) you will be able to define a new type that can be multiplied by an integer in either order, even though theint
class has known nothing of it for more than a century.By the way, the string class's
__mul__()
has a bug in some versions of Python. If it doesn't know how to multiply itself by an object, it raises aTypeError
instead of returningNotImplemented
. That means you can't multiply a string by a user-defined type even if the user-defined type has an__rmul__()
method, because the string never lets it have a chance. The user-defined type has to go first (e.g.Foo() * 'bar'
instead of'bar' * Foo()
) so its__mul__()
is called. They seem to have fixed this in Python 2.7 (I tested it in Python 3.2 also), but Python 2.6.6 has the bug.二元运算符本质上有两个操作数。每个操作数可以位于运算符的左侧或右侧。当您为某种类型重载运算符时,您可以指定对运算符的哪一侧进行重载。当对两个不同类型的操作数调用运算符时,这非常有用。下面是一个示例:
这里,
obj
将是一个带有val = 24
的Bar
,但对obj2
的赋值会生成错误,因为Bar
没有__mul__
并且Foo
没有__rmul__
。我希望这已经足够清楚了。
Binary operators by their nature have two operands. Each operand may be on either the left or the right side of an operator. When you overload an operator for some type, you can specify for which side of the operator the overloading is done. This is useful when invoking the operator on two operands of different types. Here's an example:
Here,
obj
will be aBar
withval = 24
, but the assignment toobj2
generates an error becauseBar
has no__mul__
andFoo
has no__rmul__
.I hope this is clear enough.
__mul__()
是点积的情况,点积的结果应该是标量或只是一个数字,即__mul__()
结果是点积乘法就像x1*x2+y1*y2
。在 __rmul__() 中,结果是具有x = x1*x2
和y = y1*y2
的点。__mul__()
is the case of a dot product and the result of the dot product should be a scalar or just a number, i.e.__mul__()
results in a dot product multiplication likex1*x2+y1*y2
. In__rmul__()
, the result is a point withx = x1*x2
andy = y1*y2
.