Python:使用星号(*)将两个对象“相乘”在一起是什么意思?

时间:2018-07-11 20:34:09

标签: python object syntax

关于类,我有点Python新手。我已经看到一些脚本包含的行似乎将“类”实例“相乘”在一起。例如:

Z = X * Y

其中X和Y是两个不同类的实例。

*符号的含义是什么,它如何应用于Python中的类(或类的实例)?

在大多数情况下,*与乘法有关,但我不明白“乘”类的含义。

任何信息都会受到赞赏。

1 个答案:

答案 0 :(得分:3)

*运算符的意思只是“乘”。

但是两个对象相乘的含义取决于这些对象的类型。

对于所有内置和stdlib类型,如果有意义,则表示乘法;如果没有意义,则表示TypeError。例如:

>>> 2 * 3
6
>>> (1, 2, 3) * 3
(1, 2, 3, 1, 2, 3, 1, 2, 3)
>>> "abc" * "def"
TypeError: can't multiply sequence by non-int of type 'str'

由于乘法对于类对象没有意义,因此它们是TypeError的一种类型:

>>> class C: pass
>>> C * 2
TypeError: unsupported operand type(s) for *: 'type' and 'int'

如果您(或第三方库作者)创建新类型,则可以决定乘法的含义。文档的Emulating numeric types中介绍了执行此操作的方法,但简短的版本是您定义了__mul__方法:

class MyNumberyThing:
    def __init__(self, n):
        self.n = n
    def __repr__(self):
        return f'MyNumberyType({self.n})'
    def __mul__(self, other):
        if isinstance(other, MyNumberyThing):
            return MyNumberyThing(self.n * other.n)
        elif isinstance(other, int):
            return MyNumberyThing(self.n * other)
        elif isinstance(other, float):
            raise TypeError("sorry, can't multiply by float because of precision issues")
        else:
            raise TypeError(f"sorry, don't know how to multiply by {type(other).__name__}")

请注意,这使得 {em> MyNumberyThing的实例是可乘的。它不会使MyNumberyThing本身可乘(MyNumberyThing不是MyNumberyThing,而是type):

>>> n = MyNumberyThing(2)
>>> n * 3
MyNumberyType(6)
>>> MyNumberyThing * 3
TypeError: unsupported operand type(s) for *: 'type' and 'int'

当然,没有什么可以阻止您定义一些荒谬的东西:

class MySillyThing:
    def __mul__(self, other):
        self.storage = -other
        print(f'I took your {other}')

>>> silly = MySillyThing()
>>> silly * 3
I took your 3
>>> silly.storage
-3

...当然,除了没有人会理解您的代码这一事实。 (六个月后,“没有人”包括您在内,试图调试您认为已经完成的事情……)


请注意,Python实际上有两种拼写“乘法”的方式:*@

所有内置类型都忽略@,因此,如果尝试使用TypeError,则只会得到它。基本上,它的用途是,因此NumPy可以使用*进行元素乘法,而使用@进行矩阵乘法。 (@运算符的魔术方法甚至被称为__matmul__。)但是当然,同样需要进行两种不同乘法运算的其他第三方库也可以将@用于第二种。