FizzBuzz 列表理解
FizzBuzz list comprehension
在学习 python 的过程中,我一直在摆弄一些不同的 fizz buzz 脚本。我遇到了这个效果很好但我无法理解它是如何工作的。我知道正常的嘶嘶声如何与 for 循环和 "if i % 3 == 0 and i % 5 == 0" 一起工作。让我难过的是 "Fizz"(not i%3) + "Buzz “(不是 i%5)” 有效。
x = ["Fizz"*(not i%3) + "Buzz"*(not i%5) or i for i in range(1, 100)]
>>> 3%3
0
>>> not 3%3
True
>>>
>>> 3%2
1
>>> not 3%2
False
>>>
>>> if 0:
... print 'true'
...
>>> if 1:
... print 'true'
...
true
>>> False * 'Fizz'
''
>>> True * 'Fizz'
'Fizz'
您可以看到 3%3
的计算结果为 0
,而 0
的计算结果为 False。 1
计算结果为真。
在理解中,它循环遍历从 1 到 99 的每个数字,如果 i%3
的计算结果为 True
或 i=3; 3%3
,则打印 "Fizz"
并且如果 i%5 == 0
.
,"Buzz"
也是如此
如果 "Fizz"
和 "Buzz"
都没有被打印,or
之前的部分在这里:"Fizz"*(not i%3) + "Buzz"*(not i%5) or i
计算为 ''+''
所以 or
打印了部分条件,也就是 i
.
在 python 中,您可以使用乘法运算符复制字符串:
print('aaa' * 3) # aaaaaaaaa
此外,布尔值在乘法时被隐式转换为整数。因此,如果你这样做
"Fizz"*(not i%3)
首先,i%3 将return取模的结果。然后,如果结果为 0,not
运算符会将其转换为 True
,否则将其转换为 False
(通过将其转换为布尔值,然后取反该值)。然后应用乘法运算符,False
变为 0,True
变为 1。
因此,如果数字可以被 3 整除,我们得到 0 作为模的结果,应用 not
时得到 True
,乘法时得到 1,而字符串 Fizz
作为乘法的结果复制了 1 次。如果它不可整除,我们得到 0 作为乘法的操作数,有效地将字符串 Fizz
复制 0 次,因此是一个空字符串。
Buzz
也是如此,范围内每个i
的结果只是两者的串联。
如您所知,%
运算符 return 是给定股息和除数的余数。此操作仅returns 0
当操作returns 无余数。
例如,如果i % 3 == 0
,则3
是i
的因数。因此,当3
或5
可以除i
时,i % 3 and i % 5
只会return0
。
因此 not i % 3
只有 return 1
如果 i
可以被 3
整除。 not
语句反转输出,其中非零余数 (true
) 变为 0 值 (false
)。同样,零余数将成为值 1
(true
).
当像"Fizz"
这样的字符串乘以0
时,它将变成空字符串。当乘以 1
时,它将保持不变。我相信这是由于字符串的数字表示,但如果不是这种情况,有人可以纠正我。
因此,"Fizz"
and/or "Buzz"
将仅存在于该表达式的输出中,如果 i % 3
and/or i % 5
return 0
余数。意思是 i
可以被 3
and/or 5
.
整除
列表理解表示为
L = [mapping-expression for element in source-list if filter-expression]
现在,将 "for element in source-list" 部分替换为
for i in range(1, 100)
迭代包含 1 到 99 整数的列表,一次返回一个整数。
"mapping-expression"这里是
"Fizz"*(not i%3) + "Buzz"*(not i%5) or i
它使用我从 "for i in range(1, 100)"
返回的整数
当 i 可被 3 或 5 整除时,i % 3 和 i % 5 returns 0,当 i 不可整除时返回任何其他整数。
(not i % 3) # return True when i is divisible by 3
(not i % 5) # returns False when i is not divisible by 5
当从 (not i % 3) 或 (not i % 5) 返回的布尔值乘以字符串 "Fizz" 和 "Buzz":
"Fizz" * True # returns "Fizz"
"Buzz" * False # returns ""
然后将上面返回的字符串连接起来
"Fizz" + ""
因此 "Fizz" 被放置在结果列表中并且这个过程在每次迭代中继续进行,返回 "Fizz" 或 "Buzz" 或有时乘以整数 i 本身字符串布尔乘法 returns 一个空字符串 ""。自
"" + "" or i # returns i
结果列表类似于 [1, 2, 'Fizz', 4, 'Buzz', 'Fizz', 7, 8, 'Fizz', 'Buzz', 11, 'Fizz', 13, 14, 'FizzBuzz' ......]
注意:示例中未使用可选 "if filter-expression"。
我个人最喜欢的:
#!python
from __future__ import print_function
def fizz_buzz(lower=1, upper=101):
return ["Fizz"*(x % 3 == 0) + "Buzz"*(x % 5 == 0) or str(x) \
for x in range(lower, upper)]
print('\n'.join(fizz_buzz()))
所有操作都在列表理解表达式中,其中大部分是在条件表达式中,该表达式的计算结果为字符串("Fizz"、"Buzz" 或 "Fizz"+"Buzz") 或被评估的整数的字符串表示形式。
这依赖于 Python 相对不寻常(甚至可能晦涩难懂)的 * 字符串运算符...通过复制和连接 "multiply" 字符串...以及 Python关于评估"truth."的语义(在Python空序列中:字符串、列表和元组,以及其他空容器、字典和集合,以及数字零值都是"false" --- 以及特殊的 None 和 False 对象)。
回到你的问题。 Python 将 "multiplying a string by zero" 视为空字符串。它还在任何算术上下文(例如乘法)中将布尔对象视为 1 或 0。因此,如果对象可以被 3 整除,则 not i%3 的布尔值是 True ... 即模 3 运算 returns 非零值。所以这些字符串中的每一个都是 "multiplied" 一个或零(相当于调用 int(not(bool(i%X))) ... 其中 X 是 3 in一个子表达式和另一个子表达式中的 5。(注意:not 是一元运算符,不是函数;但它可以像函数调用一样编写,因为 not(x) 与 not x 的计算结果相同......在大多数情况下,多余的括号是无害的)。
我更喜欢精确地返回(或产生)整数的字符串转换,因为您可以在其他函数中以自然的方式使用此表达式的结果(例如调用 string.join() 方法).
您可以使用:
["Fizzbuzz" if (i%3 == 0 and i %5 == 0) else "Fizz" if (i%3 == 0) else "Buzz" if (i%5 == 0) else i for i in x]
希望一切顺利。
尝试这样的事情:
def fizz_buzz(upper):
up_limit = upper +1
fbl = ['fb' if i%15 == 0 #fizzbuzz if divisible by both
else 'f' if i%3 == 0 #fizz if divisible by 3
else 'b' if i%5 == 0 #buzz if divisible by 5
else i #else present number
for i in range(1,up_limit)]
return fbl
我认为以下方法有助于我理解列表理解结构。
def fizzBuzz(upper_limit):
def mapper(a):
result = ''
if a % 3 == 0:
result = result + 'Fizz'
if a % 5 == 0:
result = result + 'Buzz'
return result
return [mapper(x) if mapper(x) else x for x in range(1,upper_limit+1)]
fizzBuzz(16)
[1,2,'Fizz',4,'Buzz','Fizz',7,8,'Fizz','Buzz', 11,'Fizz',13,14,'FizzBuzz',16]
在学习 python 的过程中,我一直在摆弄一些不同的 fizz buzz 脚本。我遇到了这个效果很好但我无法理解它是如何工作的。我知道正常的嘶嘶声如何与 for 循环和 "if i % 3 == 0 and i % 5 == 0" 一起工作。让我难过的是 "Fizz"(not i%3) + "Buzz “(不是 i%5)” 有效。
x = ["Fizz"*(not i%3) + "Buzz"*(not i%5) or i for i in range(1, 100)]
>>> 3%3
0
>>> not 3%3
True
>>>
>>> 3%2
1
>>> not 3%2
False
>>>
>>> if 0:
... print 'true'
...
>>> if 1:
... print 'true'
...
true
>>> False * 'Fizz'
''
>>> True * 'Fizz'
'Fizz'
您可以看到 3%3
的计算结果为 0
,而 0
的计算结果为 False。 1
计算结果为真。
在理解中,它循环遍历从 1 到 99 的每个数字,如果 i%3
的计算结果为 True
或 i=3; 3%3
,则打印 "Fizz"
并且如果 i%5 == 0
.
"Buzz"
也是如此
如果 "Fizz"
和 "Buzz"
都没有被打印,or
之前的部分在这里:"Fizz"*(not i%3) + "Buzz"*(not i%5) or i
计算为 ''+''
所以 or
打印了部分条件,也就是 i
.
在 python 中,您可以使用乘法运算符复制字符串:
print('aaa' * 3) # aaaaaaaaa
此外,布尔值在乘法时被隐式转换为整数。因此,如果你这样做
"Fizz"*(not i%3)
首先,i%3 将return取模的结果。然后,如果结果为 0,not
运算符会将其转换为 True
,否则将其转换为 False
(通过将其转换为布尔值,然后取反该值)。然后应用乘法运算符,False
变为 0,True
变为 1。
因此,如果数字可以被 3 整除,我们得到 0 作为模的结果,应用 not
时得到 True
,乘法时得到 1,而字符串 Fizz
作为乘法的结果复制了 1 次。如果它不可整除,我们得到 0 作为乘法的操作数,有效地将字符串 Fizz
复制 0 次,因此是一个空字符串。
Buzz
也是如此,范围内每个i
的结果只是两者的串联。
如您所知,%
运算符 return 是给定股息和除数的余数。此操作仅returns 0
当操作returns 无余数。
例如,如果i % 3 == 0
,则3
是i
的因数。因此,当3
或5
可以除i
时,i % 3 and i % 5
只会return0
。
因此 not i % 3
只有 return 1
如果 i
可以被 3
整除。 not
语句反转输出,其中非零余数 (true
) 变为 0 值 (false
)。同样,零余数将成为值 1
(true
).
当像"Fizz"
这样的字符串乘以0
时,它将变成空字符串。当乘以 1
时,它将保持不变。我相信这是由于字符串的数字表示,但如果不是这种情况,有人可以纠正我。
因此,"Fizz"
and/or "Buzz"
将仅存在于该表达式的输出中,如果 i % 3
and/or i % 5
return 0
余数。意思是 i
可以被 3
and/or 5
.
列表理解表示为
L = [mapping-expression for element in source-list if filter-expression]
现在,将 "for element in source-list" 部分替换为
for i in range(1, 100)
迭代包含 1 到 99 整数的列表,一次返回一个整数。
"mapping-expression"这里是
"Fizz"*(not i%3) + "Buzz"*(not i%5) or i
它使用我从 "for i in range(1, 100)"
返回的整数当 i 可被 3 或 5 整除时,i % 3 和 i % 5 returns 0,当 i 不可整除时返回任何其他整数。
(not i % 3) # return True when i is divisible by 3
(not i % 5) # returns False when i is not divisible by 5
当从 (not i % 3) 或 (not i % 5) 返回的布尔值乘以字符串 "Fizz" 和 "Buzz":
"Fizz" * True # returns "Fizz"
"Buzz" * False # returns ""
然后将上面返回的字符串连接起来
"Fizz" + ""
因此 "Fizz" 被放置在结果列表中并且这个过程在每次迭代中继续进行,返回 "Fizz" 或 "Buzz" 或有时乘以整数 i 本身字符串布尔乘法 returns 一个空字符串 ""。自
"" + "" or i # returns i
结果列表类似于 [1, 2, 'Fizz', 4, 'Buzz', 'Fizz', 7, 8, 'Fizz', 'Buzz', 11, 'Fizz', 13, 14, 'FizzBuzz' ......]
注意:示例中未使用可选 "if filter-expression"。
我个人最喜欢的:
#!python
from __future__ import print_function
def fizz_buzz(lower=1, upper=101):
return ["Fizz"*(x % 3 == 0) + "Buzz"*(x % 5 == 0) or str(x) \
for x in range(lower, upper)]
print('\n'.join(fizz_buzz()))
所有操作都在列表理解表达式中,其中大部分是在条件表达式中,该表达式的计算结果为字符串("Fizz"、"Buzz" 或 "Fizz"+"Buzz") 或被评估的整数的字符串表示形式。
这依赖于 Python 相对不寻常(甚至可能晦涩难懂)的 * 字符串运算符...通过复制和连接 "multiply" 字符串...以及 Python关于评估"truth."的语义(在Python空序列中:字符串、列表和元组,以及其他空容器、字典和集合,以及数字零值都是"false" --- 以及特殊的 None 和 False 对象)。
回到你的问题。 Python 将 "multiplying a string by zero" 视为空字符串。它还在任何算术上下文(例如乘法)中将布尔对象视为 1 或 0。因此,如果对象可以被 3 整除,则 not i%3 的布尔值是 True ... 即模 3 运算 returns 非零值。所以这些字符串中的每一个都是 "multiplied" 一个或零(相当于调用 int(not(bool(i%X))) ... 其中 X 是 3 in一个子表达式和另一个子表达式中的 5。(注意:not 是一元运算符,不是函数;但它可以像函数调用一样编写,因为 not(x) 与 not x 的计算结果相同......在大多数情况下,多余的括号是无害的)。
我更喜欢精确地返回(或产生)整数的字符串转换,因为您可以在其他函数中以自然的方式使用此表达式的结果(例如调用 string.join() 方法).
您可以使用:
["Fizzbuzz" if (i%3 == 0 and i %5 == 0) else "Fizz" if (i%3 == 0) else "Buzz" if (i%5 == 0) else i for i in x]
希望一切顺利。
尝试这样的事情:
def fizz_buzz(upper):
up_limit = upper +1
fbl = ['fb' if i%15 == 0 #fizzbuzz if divisible by both
else 'f' if i%3 == 0 #fizz if divisible by 3
else 'b' if i%5 == 0 #buzz if divisible by 5
else i #else present number
for i in range(1,up_limit)]
return fbl
我认为以下方法有助于我理解列表理解结构。
def fizzBuzz(upper_limit):
def mapper(a):
result = ''
if a % 3 == 0:
result = result + 'Fizz'
if a % 5 == 0:
result = result + 'Buzz'
return result
return [mapper(x) if mapper(x) else x for x in range(1,upper_limit+1)]
fizzBuzz(16)
[1,2,'Fizz',4,'Buzz','Fizz',7,8,'Fizz','Buzz', 11,'Fizz',13,14,'FizzBuzz',16]