2015-02-24 61 views
4

因此,我正在学习Python,并通过一系列程序思想工作。当然,我写了强制性的FizzBu​​zz,它工作,但基本上,如果elif其他blablabla。我GOOGLE了它,看看是否有其他的方法,发现了这个潮湿的一行代码:它为什么有效?

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

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

回答

2

没有如果,没有elifs,什么都没有。

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

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

意味着 “一个Fizz如果i % 3 == 0,如果没有没有。”与Buzz相同。

最后,那or i最后意味着如果你得到了空字符串,因为这两个部分都是空的,那么你会得到ior的意思是“左边的值,除非左边是错误的值,在这种情况下返回右边的值”。

这个技巧也被其他地方使用。 Python没有与C的?:运算符直接等价,但是由于上面提到的bool-to-integer转换,您可以接近具有两元素元组和索引操作的元素。所以C的

a? b: c 

这意味着 “b如果a是真实的,否则c” 成为这个在Python:

(c, b)[a] 
+6

三元运算符的Python等价物是'b if a else c'。 – augurar 2015-02-24 00:47:47

2

你要打印字符串"Buzz"要么一旦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 

同样的逻辑也适用于“菲斯”有时(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"

布尔数据类型为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' 
+0

实际上,乘数是布尔值。 – volcano 2015-02-24 00:37:45

+0

@volcano,这正是我在我的答案 – 2015-02-24 00:38:38

+0

@augurarm它是一个int的sublcass,因为我已经在我的回答中说过 – 2015-02-24 00:52:16

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

1

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

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

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

所以string * False ==空字符串

以嘶嘶声和被上述返回的嗡嗡声弦和使用+运营商将它们连接起来。

现在在打印语句中,如果该连接的结果是空字符串,则or运算符将使用值i代替。

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

1

如果你只考虑条件:

(i % 3 == 0) 

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

关于Python中字符串的很酷的事情是,您可以有条件地打印一个字符串。例如,启动了一个翻译,输入:

'foo' * True 
'foo' * False 

这将导致下面的输出:

'foo' 
'' 

所以基本上,因为我的给定值,你这样做:

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") 
.... 

这就是“潮湿”的衬里是如何工作的。

相关问题