FizzBu​​zz 列表理解

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 的计算结果为 Truei=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,则3i的因数。因此,当35可以除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" --- 以及特殊的 NoneFalse 对象)。

回到你的问题。 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]