我正在研究一些不同的方法来解决经典的FizzBuzz问题,并偶然发现了这个问题:
for i in xrange(1, n+1):
print "Fizz"*(i%3 == 0) + "Buzz"*(i%5 == 0) or i
if
声明的星号是否是简写?如果是,这种表示法是否特定于print
?
提前致谢。
答案 0 :(得分:9)
Python中的星号实际上只是标准的乘法运算符*
。它映射到它所操作的对象的__mul__
方法,因此可以重载以具有自定义含义。这与if
或print
没有任何关系。
对于字符串(str
和unicode
),它已被重载/重写,表示重复字符串,"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 == 1
和False == 0
如果你“乘以”使用布尔值的字符串,您将获得相同的字符串输出或空字符串。
注意:我还要注意,根据我的经验/理解,Python中不鼓励这种类型的编程风格 - 它使代码的可读性降低(对于新手和老朋友而言) )以及没有更快(事实上,可能更慢;请参阅http://pastebin.com/Q92j8qga以获得快速基准(但有趣的是,不是在PyPy中:http://pastebin.com/sJtZ6uDm))。
*
也适用于list
和tuple
的实例:
>>> [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__
的情况也适用于“原始”类型,例如int
,float
和其他类型,因此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
如果Fizz
或Buzz
为非零/ True,则python甚至不会评估i
Fizz
为真(因此,对于所有可以除以3的i值,它输出3)
类似地,Buzz
对于所有5次乘法都是正确的。
当我被除以15时输出Fizz
和Buzz
。
当以上两个条件都为假时,我会被评估和打印。