它为什么有效?

时间:2015-02-24 00:31:30

标签: python string printing concatenation fizzbuzz

所以我正在学习Python并通过一系列程序思想。当然我写了强制性的FizzBu​​zz,它起作用了,但基本上就是elif else blablabla。我用谷歌搜索它是否有其他方法,并发现这个潮湿的单行:

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

没有ifs,没有elifs,没有。我用google搜索“字符串连接”并在*符号上找到了信息,但是不明白它在这种情况下是如何工作的。有人可以解释一下吗?

6 个答案:

答案 0 :(得分:2)

"Buzz"为True或返回if (i % 5 == 0)时,您将打印字符串i

In [5]: "foo" * 2
Out[5]: 'foofoo'

In [6]: "foo" * 3
Out[6]: 'foofoofoo'

In [7]: i = 5
In [8]: "foo" *  (i % 5 == 0) or i
Out[9]: 'foo'  
In [9]: "foo" *  (i % 5 == 1) or i
Out[22]: 5

同样的逻辑适用于" Fizz"有时候(i % 3 == 0)会是真的,所以我们会看到它一次,如果它是假的,我们就不会看到它。

当你在字符串上使用*运算符时,它会重复字符串n次,在这种情况下它最多只会一次,因为只根据布尔测试的结果打印字符串

你可以在ipython中看到TrueFalse的具体信息:

In [26]: "foo" * True
Out[26]: 'foo'

In [27]: "foo" * False
Out[27]: ''

基本上True * "foo"相当于1 * "foo" "foo" * False相当于0 * "foo"

Bool是int的子类,所以代码利用了这个事实,你有时看到类似的逻辑用于基于测试索引列表,尽管不推荐:

In [31]: d = ["bar","foo"]   
In [32]: d[3<2] # False so we get 0 the first element
Out[32]: 'bar'   
In [33]: d[3>2] # True so we get 1 the second element
Out[33]: 'foo'

答案 1 :(得分:2)

分解它,你会理解它。

def does_it_fizz(num):
    return num % 3 == 0

def does_it_buzz(num):
    return num % 5 == 0

for num in range(1, 101):
    print("Fizz" * does_it_fizz(num) + "Buzz" * does_it_buzz(num) or num)

字符串乘法重复该字符串,因此'a' * naaaaa...n times...a。如果i % 3 != 0,则does_it_fizz(i)会返回0"any string" * 0 == ""。如果数字既不应该是Fizz也不应该是Buzz,那么你得print("" or num)。空字符串为Falsey,但num始终为Truthy,因此它会打印num

答案 2 :(得分:2)

  

没有ifs,没有elifs,没有。

当然有!只是伪装。寻找字符串连接(即+)不会帮助您,因为*重复。具体来说,字符串* n为您提供一个字符串,该字符串是一行中的n个字符串副本。此外,布尔值可以隐式转换为整数:True变为1False变为0。所以

"Fizz" * (i % 3 == 0)

表示&#34;如果Fizz,则为i % 3 == 0,否则为无。&#34;与Buzz相同。

最后,or i最后意味着如果你得到空字符串,因为两个部分都是空的,那么你得到ior实际上意味着&#34;左侧的值,除非左侧是假值,在这种情况下返回右侧的值。&#34;

这个技巧也被其他地方使用了。 Python并没有直接等同于C ?:运算符,但是由于bool-to-integer转换,你可以接近一个带有两元素元组和索引操作的运算符。上文提到的。所以C&#39>

a? b: c
如果b为真,则

表示&#34; a,否则为c&#34;在Python中成为这个:

(c, b)[a]

答案 3 :(得分:1)

i == 3时,(i % 3 == 0)将为True。

任何字符串* True都将返回字符串。在这种情况下,将True视为整数1会有所帮助(因为任何乘以1的东西都是乘以的原始事物。)

例如。 i == 1(i % 3 == 0)将为假(as 1 % 3 == 1)

所以string * False ==空字符串

获取上面返回的fizz和buzz字符串,并使用+运算符将它们连接起来。

现在在print语句中,如果该连接的结果是空字符串,or运算符将改为使用i的值。

答案 4 :(得分:1)

以下是对所发生情况的细分:

for i in range(1,101):
    if (i % 3 == 0):
        print "Fizz"
    if (i % 5 == 0):
        print "Buzz"
    if (i % 5 != 0 and (i % 3 != 0)):
        print i

我的ide设置为Python 2.7 btw

答案 5 :(得分:1)

如果你只考虑条件:

(i % 3 == 0)

这会生成一个布尔值,表示i modulo 3的特定值是否等于0.这是3的倍数或0(0,3,6等)的情况。所以这就是你如何知道打印“Fizz”(或“Buzz”,给定其他条件)。

Python中关于字符串的一个很酷的事情是你可以有条件地打印一个字符串。例如,启动一个解释器并键入:

'foo' * True
'foo' * False

这应该导致以下输出:

'foo'
''

所以基本上,对于i的给定值,你这样做:

print("Fizz" * (0 % 3 == 0) + "Buzz" * (0 % 5 == 0) or i) -> print("Fizz" * True + "Buzz" * True or i) -> printf('Fizz'+'Buzz')
print("Fizz" * (1 % 3 == 0) + "Buzz" * (1 % 5 == 0) or i) -> print("Fizz" * False + "Buzz" * False or i) -> printf(1)
print("Fizz" * (2 % 3 == 0) + "Buzz" * (2 % 5 == 0) or i) -> print("Fizz" * False + "Buzz" * False or i) -> printf(2)
print("Fizz" * (3 % 3 == 0) + "Buzz" * (3 % 5 == 0) or i) -> print("Fizz" * True + "Buzz" * False or i) -> printf("Fizz")
....

这就是“潮湿”的一条班轮的运作方式。