Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'for' loop in one line in Python [duplicate]

When I tried to use a for statement in one line like below,

def get_cubes(x):
ls=[]
ls.append(pow(item*3, 3)) for item in range(int((x-x%3)/3)+1)
return ls

there was always an error:

File "<ipython-input-47-8c391c3d568a>", line 3
ls.append(pow(item*3, 3))  for item in range(int((x-x%3)/3)+1)
                             ^
SyntaxError: invalid syntax

But when I write it in a regular for loop method, it works well. Why?

like image 795
z-one ng Avatar asked Sep 22 '18 18:09

z-one ng


2 Answers

 Solution

If you strictly want a one-liner, then this is the solution:

get_cubes = lambda x: [pow(i, 3) for i in range(0, x+1, 3)]

But since clarity and readability should always be a priority in Python, it's better to write it as a function just like @daniel did:

def get_cubes(x):
    return [pow(i, 3) for i in range(0, x+1, 3)]

 Output

Using a for loop to test the function you get the following results:

for i in range(20):
    print(i, ':', get_cubes(i))

0 : [0]
1 : [0]
2 : [0]
3 : [0, 27]
4 : [0, 27]
5 : [0, 27]
6 : [0, 27, 216]
7 : [0, 27, 216]
8 : [0, 27, 216]
9 : [0, 27, 216, 729]
10 : [0, 27, 216, 729]
11 : [0, 27, 216, 729]
12 : [0, 27, 216, 729, 1728]
13 : [0, 27, 216, 729, 1728]
14 : [0, 27, 216, 729, 1728]
15 : [0, 27, 216, 729, 1728, 3375]
16 : [0, 27, 216, 729, 1728, 3375]
17 : [0, 27, 216, 729, 1728, 3375]
18 : [0, 27, 216, 729, 1728, 3375, 5832]
19 : [0, 27, 216, 729, 1728, 3375, 5832]

Explanation

For those who asked why @daniel's code work:

The original code does the following:

  1. Given an x, iterate from 0 to the number of times 3 divides x plus 1.
  2. For each x, multiply it by 3 and raise it to the power of 3
  3. Return the list containing the results of step 2

Step 1 was originally written as

range(int((x - x%3) / 3) + 1)

which subtracts the reminder of a number when divided by 3 and then divides that result by 3 before adding 1. But the same result can be achieved by just getting the integer part of dividing x by 3 and then adding 1 which will look something like this:

int(x / 3) + 1

Step 2 multiplies each iteration by 3 before raising it to the power of 3 but that "multiplication" can be achieved as well by using ranges (just like @daniel did) using:

range(0, x+1, 3)

which iterate from 0 to x+1 on steps of 3 and yields the same results. I.e x being 10:

range(0, 10 + 1, 3)  |    i*3 for i in range(int(x / 3) + 1)
============================================================
0                    |    0*3 = 0
3                    |    1*3 = 3
6                    |    2*3 = 6
9                    |    3*3 = 9

For the Step 3 we just need to apply pow(x, 3) (or x ** 3) and we can fit everything in a single line using list comprehension, then we can fit that in a lambda function or inside the return statement of a function.

[pow(i, 3) for i in range(0, x+1, 3)]
like image 162
pablotrinidad Avatar answered Sep 28 '22 16:09

pablotrinidad


The correct syntax for for-loops is

def get_cubes(x):
    ls = []
    for item in range(int((x-x%3)/3)+1):
        ls.append(pow(item*3, 3)) 
    return ls

Perhaps, you are looking for list comprehension, which is a way to generate lists, when the loop body only appends to a list:

def get_cubes(x):
    ls = [(item*3) ** 3 for item in range(int((x-x%3)/3)+1)]
    return ls

or in short:

def get_cubes(x):
    return [i ** 3 for i in range(0, x+1, 3)]
like image 43
Daniel Avatar answered Sep 28 '22 17:09

Daniel