Why does it work?

So, I am learning Python and browsing through a list of programming ideas. Of course, I wrote a mandatory FizzBuzz that worked, but was mostly if elif else blablabla. I looked for it to see if there are other ways and found this wet liner:

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

No ifs, no elifs, nothing. I googled "string concatenation" and found information about the * character, but don't understand how it works in this case. Can someone explain?

+4
source share
6 answers

No ifs, no elifs, nothing.

Of course have! Just disguised. Finding string concatenation (i.e. + ) won't help you, because * is a repetition. In particular, string * n gives you a string containing n copies of the string in the string. In addition, a boolean value can be implicitly converted to an integer: True becomes 1 and False becomes 0 . So

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

means "One Fizz if i % 3 == 0 , none if not." Same thing with Buzz .

Finally, or i at the end means that if you got an empty string because both parts came up empty, then instead you get i . or really means "the value of the left side, unless the left side is a false value, in which case it returns the value of the right side."

This trick is used elsewhere. Python does not have a direct equivalent to the C ?: Operator, but you can come close to one with a two-element tuple and index operation due to the bool-to-integer conversion mentioned above. So C

 a? b: c 

which means " b if a true, otherwise c " becomes in Python:

 (c, b)[a] 
+2
source

You are going to print the string "Buzz" either once if (i % 5 == 0) is True, or return 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 

The same applies to "Fizz", sometimes (i % 3 == 0) will be True, so we see it once, when it is False, we do not see it.

When you use the * operator in a line, it will repeat the line n times, in which case it will be no more, because either the line will be printed only based on the result of a boolean test.

In ipython, you can see what happens with True and False :

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

Basically True * "foo" equivalent to 1 * "foo" "foo" * False equivalent to 0 * "foo"

Bool is a subclass of int, so the code uses this fact, sometimes you see the same logic used to index the list based on the test, but it is not recommended:

 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' 
+2
source

Break it and you will understand it.

 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) 

Multiplication of lines repeats a line, therefore 'a' * n - aaaaa...n times...a . if i % 3 != 0 , then does_it_fizz(i) returns 0 . "any string" * 0 == "" . If the number should not be either Fizz or Buzz, you will get print("" or num) . The empty string is Falsey, but num always Truthy, so it prints num

+2
source

When i == 3 , (i % 3 == 0) will be True.

Any string * True will return a string. This helps to think of True as an integer 1 in this case (since everything that is multiplied by 1 is the original thing that was multiplied).

When, for example. i == 1 , (i % 3 == 0) will be False (as 1 % 3 == 1) .

So string * False == empty string

Take the fizz lines and buzz lines that were returned above and combine them using the + operator.

Now in the print statement, if the result of this concatenation is an empty string, the or operator will use the value of i instead.

+1
source

Here is a breakdown of what happens:

 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 

My ideal is installed on Python 2.7 btw

+1
source

If you consider only conditional:

 (i % 3 == 0) 

this generates a boolean that determines whether this particular value of I modulo 3 is 0. This is the case for a multiple of 3 or 0 (0, 3, 6, etc.). So this is how you know to print “Fizz” (or “Buzz”, given other conditionals).

The great thing about strings in Python is that you can conditionally print a string. For example, run the interpreter and enter this:

 'foo' * True 'foo' * False 

This should lead to the following conclusion:

 'foo' '' 

So basically, for a given value, I do you do this:

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

Here's how a raw one liner works.

+1
source

Source: https://habr.com/ru/post/1214063/


All Articles