什么情况下调用__rmul__?

发布于 2024-10-20 06:25:17 字数 115 浏览 1 评论 0原文

假设我有一个列表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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

哆啦不做梦 2024-10-27 06:25:17

当 Python 尝试将两个对象相乘时,它首先尝试调用左侧对象的 __mul__() 方法。如果左侧对象没有 __mul__() 方法(或者该方法返回 NotImplemented,表明它不适用于相关的右侧操作数),则 Python想知道正确的对象是否可以进行乘法运算。如果右操作数与左操作数的类型相同,Python 就知道它不能,因为如果左操作数不能做到这一点,那么相同类型的另一个对象当然也不能。

不过,如果这两个对象是不同的类型,Python 认为值得一试。然而,它需要某种方式来告诉正确的对象,它是操作中的正确对象,以防操作不可交换。 (当然,乘法是,但并非所有运算符都是,并且在任何情况下 * 并不总是用于乘法!)因此它调用 __rmul__() 而不是 __mul__()

作为示例,请考虑以下两个语句:

print "nom" * 3
print 3 * "nom"

在第一种情况下,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 returns NotImplemented, 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:

print "nom" * 3
print 3 * "nom"

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__() returns NotImplemented 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 the str 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 the int 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 a TypeError instead of returning NotImplemented. 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.

街角迷惘 2024-10-27 06:25:17

二元运算符本质上有两个操作数。每个操作数可以位于运算符的左侧或右侧。当您为某种类型重载运算符时,您可以指定对运算符的哪一侧进行重载。当对两个不同类型的操作数调用运算符时,这非常有用。下面是一个示例:

class Foo(object):
    def __init__(self, val):
        self.val = val

    def __str__(self):
        return "Foo [%s]" % self.val


class Bar(object):
    def __init__(self, val):
        self.val = val

    def __rmul__(self, other):
        return Bar(self.val * other.val)

    def __str__(self):
        return "Bar [%s]" % self.val


f = Foo(4)
b = Bar(6)

obj = f * b    # Bar [24]
obj2 = b * f   # ERROR

这里,obj 将是一个带有 val = 24Bar,但对 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:

class Foo(object):
    def __init__(self, val):
        self.val = val

    def __str__(self):
        return "Foo [%s]" % self.val


class Bar(object):
    def __init__(self, val):
        self.val = val

    def __rmul__(self, other):
        return Bar(self.val * other.val)

    def __str__(self):
        return "Bar [%s]" % self.val


f = Foo(4)
b = Bar(6)

obj = f * b    # Bar [24]
obj2 = b * f   # ERROR

Here, obj will be a Bar with val = 24, but the assignment to obj2 generates an error because Bar has no __mul__ and Foo has no __rmul__.

I hope this is clear enough.

趁年轻赶紧闹 2024-10-27 06:25:17

__mul__() 是点积的情况,点积的结果应该是标量或只是一个数字,即 __mul__() 结果是点积乘法就像x1*x2+y1*y2。在 __rmul__() 中,结果是具有 x = x1*x2y = 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 like x1*x2+y1*y2. In __rmul__() , the result is a point with x = x1*x2 and y = y1*y2 .

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文