2016-12-10 15 views
1

私はPythonを学ぶときに、いくつかの異なるfizzバズスクリプトを使いこなしていました。私は素晴らしい作品を見に来ましたが、その仕組みを解読することはできません。私は、通常のfizzのバズがforループと "if%3 == 0、i%5 == 0"でどのように動作するかを知っています。どのような私は困惑していることはあなたがいることがわかりますか"フィズ"ない私%3)+ "バズ" (ないI%5)」作品。FizzBu​​zzリストの理解

x = ["Fizz"*(not i%3) + "Buzz"*(not i%5) or i for i in range(1, 100)] 
+0

インタラクティブなPythonセッションで小さな「i」の部分を独立して評価しようとすると、「Fizz」*(10%3ではない) 'または「Buzz」*(5%5でない)'です。 –

+0

Pythonでは、文字列の*演算子は、文字列を繰り返す回数を指定するために、文字列を正の整数で「掛ける」ことができます。だから "somestring" * 0は全くそれを繰り返さないことを意味します。それを空の文字列に置き換えます。したがって、この巧妙なリストの理解は、範囲内の各数値に対するさまざまなモジュロ(数学的な剰余)演算の数値結果に対するブール型強制に基づいて、「Fizz」、「Buzz」、「FizzBu​​zz」文字列、または整数のリストを生成する1〜100)。 –

答えて

2

のpythonでは、乗算演算子を使って、文字列を複製することができます。

また
print('aaa' * 3) # aaaaaaaaa 

は、ブール値は、暗黙的に乗算の整数にキャストされています。したがって、実行した場合、

"Fizz"*(not i%3) 

最初に、i%3はモジュロの結果を返します。 not演算子は、結果が0の場合はTrueに変換し、そうでない場合はFalseに変換します(ブール値にキャストして値を無効にする)。適用するときに乗算演算子を適用することにより、Falseが0になると数が3で割り切れる場合Trueは、このように1

になり、我々はモジュロ、Trueの結果として0を取得not、1乗算、文字列Fizzは、乗算の結果として1回複製されます。割り切れない場合は、乗算のオペランドとして0が得られ、Fizzという文字列が0回複製されるため、空文字列が有効になります。

Buzzについても同様であり、範囲内の各iの結果は、単に2つの連結である。

+0

ありがとう、martinarroyo、私はFalseが0でTrueが1であることを知っていたと思います。暗黙のうちに整数にキャストされて乗算されたものではありません。よく書かれた答えをありがとう。 – Neal

+0

ありがとうございます。それは価値の鋳造で働く非常に巧妙な方法です:D – martinarroyo

0
>>> 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%300 Falseに評価されると評価された。1 trueに評価されます。

理解では、1から99までのすべての数のループ、および場合i%3Trueまたはi=3; 3%3と評価された場合、"Fizz"が印刷され、i%5 == 0の場合は"Buzz"の場合も同様です。 "Fizz""Buzz"どちらも印刷を取得した場合

、ここorの前の部分:"Fizz"*(not i%3) + "Buzz"*(not i%5) or iはちょうどiあるので、条件のor一部が印刷され''+''に評価されます。

0

ご存知の通り、%演算子は、与えられた被除数と除数の残りの部分を返します。この操作は、操作が剰余を返さない場合にのみ0を返します。

たとえば、i % 3 == 0の場合、3は、iのファクタです。したがって、i % 3 and i % 5は、3または5iを分けることができる場合にのみ、0を返します。

したがって、は、i3で割り切れる場合、1を返します。 notステートメントは出力を反転します。ゼロ以外の剰余(true)は0の値(false)になります。同様に、ゼロ剰余は値1true)になります。

"Fizz"のような文字列に0を乗算すると、空の文字列になります。 1で乗算すると、同じままになります。私はこれが文字列の数値表現によるものだと信じていますが、そうでない場合は誰かが私を修正することができます。 i % 3及び/又はi % 5リターン0余り場合

したがって、"Fizz"及び/又は"Buzz"は、その式の出力に存在します。 i3および/または5で割り切れることを意味します。

1

リスト内包は現在

L = [mapping-expression for element in source-list if filter-expression] 

として表現され、どちらの整数を返す99の整数1を含むリストを反復

for i in range(1, 100) 

と部分「ソースリスト内の要素は、」置き換えます一度に。ここで

"マッピング発現" が "範囲(1、100)でiについて" 私はから返される整数を使用

"Fizz"*(not i%3) + "Buzz"*(not i%5) or i 

ある

iが3または5で割り切れる場合、I %3およびi%5は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 

(ない私は%3)または(iは5%ではない)文字列 "フィズ" および "バズ" と乗算される。次いで

"Fizz" * True # returns "Fizz" 
    "Buzz" * False # returns "" 

文字列が上記戻されその結果、「フィズ」として

"Fizz" + "" 

が結果リストに配置され、このプロセスは、「フィズ」または「バズ」又は時には回整数のいずれかを戻し、反復ごとに進み、連結I自体の両方の文字列ブールミューltiplicationは空の文字列 ""を返します。

 "" + "" or i # returns i 

ので、結果のリストは[1、2、 'フィズ'、4、 'バズ'、 'フィズ'、7、8、 'フィズ'、 'バズ'、11、 'フィズ' のようなものです、13,14、 'FizzBu​​zz' ......]

注:この例では、オプションの「if filter-expression」は使用されていません。

0

私の個人的な好み:

#!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())) 

すべてのアクションがリストの内包表現であり、そのほとんどが文字列(「フィズ」、または「バズ」または「フィズに評価されるのいずれかの条件式であります"+" Buzz ")または評価される整数の文字列表現に変換します。

これは、Pythonの比較的珍しい(おそらくあまりにも曖昧な)*演算子に依存しています。文字列を重複と連結で "乗算"する...そして "真理"の評価に関するPythonのセマンティクスにも依存します。 (Pythonの空のシーケンスでは、文字列、リスト、タプル、その他の空のコンテナ、辞書、セット、数値ゼロの値は全て「false」--- なしとFalseオブジェクト)。

に戻るPythonは "文字列に0を掛ける"を空の文字列として扱います。また、Booleanオブジェクトは、任意の算術コンテキスト(乗算など)で1または0として扱われます。したがって、のブール値は、オブジェクトが3で割り切れる場合、真のです。これは、モジュロ3演算ではゼロ以外の値を返します。したがって、これらの文字列のそれぞれに1または0を掛け合わせます(int(not bool(i%X))) ...ここでXは1つの部分式では3、もう一方は5です。 :は関数ではなく単項演算子ですが、(x)ではなく、xと等しいと評価されるため、関数呼び出しのように書くことができます。ほとんどの場合、余分な括弧は無害です。

整数の文字列変換を正確に返すことを好む理由は、自然な方法でこの式の結果を使用できるからです(たとえば、文字列を呼び出すときなど)join()方法)。

関連する問題