Python中的星号符号

时间:2014-04-12 21:25:38

标签: python operators operator-overloading

我正在研究一些不同的方法来解决经典的FizzBu​​zz问题,并偶然发现了这个问题:

for i in xrange(1, n+1):
    print "Fizz"*(i%3 == 0) + "Buzz"*(i%5 == 0) or i

if声明的星号是否是简写?如果是,这种表示法是否特定于print

提前致谢。

2 个答案:

答案 0 :(得分:9)

Python中的星号实际上只是标准的乘法运算符*。它映射到它所操作的对象的__mul__方法,因此可以重载以具有自定义含义。这与ifprint没有任何关系。

对于字符串(strunicode),它已被重载/重写,表示重复字符串,"foo" * 5评估为"foofoofoofoofoo"

>>> 'foo' * 5  # and the other way around 5 * "foo" also works
'foofoofoofoofoo'

"Fizz" * (i % 3 == 0)只是简单的“智能”简写:

"Fizz" if i % 3 == 0 else ""

这是因为表达式i % 3 == 0计算为布尔值,而布尔值是Python中整数的子类型,因此True == 1False == 0如果你“乘以”使用布尔值的字符串,您将获得相同的字符串输出或空字符串。

注意:我还要注意,根据我的经验/理解,Python中不鼓励这种类型的编程风格 - 它使代码的可读性降低(对于新手和老朋友而言) )以及没有更快(事实上,可能更慢;请参阅http://pastebin.com/Q92j8qga以获得快速基准(但有趣的是,不是在PyPy中:http://pastebin.com/sJtZ6uDm))。


*也适用于listtuple的实例:

>>> [1, 2, 3] * 3
[1, 2, 3, 1, 2, 3, 1, 2, 3]

>>> (1, 2, 3) * 3
(1, 2, 3, 1, 2, 3, 1, 2, 3)

您还可以使用相当于operator overloading in Python的类型为您的类型定义自己的*运算符:

class Foo(object):
    def __mul__(self, other):
        return "called %r with %r" % (self, other)

print Foo() * "hello"  # same as Foo().__mul__("hello")

输出:

called <__main__.Foo object at 0x10426f090> with 'hello'

*映射到__mul__的情况也适用于“原始”类型,例如intfloat和其他类型,因此3 * 4等效到(3).__mul__(4)(和其他运营商一样)。实际上,您甚至可以继承int并为*提供自定义行为:

class MyTrickyInt(int):
    def __mul__(self, other):
        return int.__mul__(self, other) - 1
    def __add__(self, other):
        return int.__add__(self, other) * -1

print MyTrickInt(3) * 4  # prints 11
print MyTrickyInt(3) + 2  # prints -5

...但是请不要那样做:)(事实上,完全保持子类化具体类型的干净并没有伤害!)

答案 1 :(得分:1)

asterik用于python中的乘法。如果它适用于字符串,它会将字符串重复到指定的数字。例如,

print "test"*0
print "test"*1
print "test"*2

输出:

<blank line>
test
testtest

在您的情况下,您有or条件,从左到右进行评估:

print "Fizz"*(i%3 == 0) + "Buzz"*(i%5 == 0) or i 

如果FizzBuzz为非零/ True,则python甚至不会评估i

当我乘以3时,

Fizz为真(因此,对于所有可以除以3的i值,它输出3) 类似地,Buzz对于所有5次乘法都是正确的。 当我被除以15时输出FizzBuzz。 当以上两个条件都为假时,我会被评估和打印。