Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python - mechanism of () and []

Tags:

python

It looks e for e in [1, 2, 3, 4, 5] is a generator expression and (e for e in [1, 2, 3, 4, 5]) is evaluated as an generator object. Hence, I think (...) is evaluation in Python.

I suppose list(e for e in [1, 2, 3, 4, 5]) is telling the Python runtime to evaluate the iterable expression, generate its object(s), and call the list function to invoke yield until it runs out of elements.

print(list(e for e in [1, 2, 3, 4, 5]))
---
[1, 2, 3, 4, 5]

Question

What actually is [...] in the code below and what is its mechanism? [ e for e in [1, 2, 3, 4, 5] ] generates a list object, hence I suppose it is a combination of an evaluation on e for e in [1, 2, 3, 4, 5] to create a generator object and invoking a call to the generator object. Is it a alias of a function call to list(...)?

print([ e for e in [1, 2, 3, 4, 5] ])
---
[1, 2, 3, 4, 5]

For the list access with a slice object, I suppose [1:3] is telling Python to evaluate the 1:3 expression to generate a slice object.

print([1,2,3][1:3])
print([1,2,3][slice(1,3,1)])
---
[2, 3]
[2, 3]

[(1:3)] fails because it tries to evaluate already evaluated 1:3?

print([1,2,3][(1:3)])
---
  File "<ipython-input-167-c20e211025dc>", line 1
    print([1,2,3][(1:3)])
                    ^
SyntaxError: invalid syntax
like image 491
mon Avatar asked Dec 30 '22 18:12

mon


1 Answers

[1, 2, 3, 4, 5] is a list literal.

value for item in iterable is a generator comprehension. list(value for item in iterable) would be calling the list() constructor with a generator, which of course just produces a list. For the purpose of reducing ambiguity, the generator comprehension cannot be used naked. But it can be used either inside a set of parentheses, or inside another expression, such as a parameter in a function call. A similar limitation applies to the := (walrus) operator added in Python 3.8.

[value for item in iterable] is a list comprehension. Note that Python treats this as an entirely separate syntactic construct.

The implementations are probably about the same, but as far as I'm aware the Python compiler detects the generator comprehension and the list comprehension separately while it processes the code, and the list comprehension is not defined as a subset/special case of either a generator comprehension or a list literal.


I'm pretty sure a similar thing applies to slice syntax - it's defined as its own syntax, specifically in the context of list indexing, and in no other context. lst[1:3] getting compiled into lst.__getitem__(slice(1, 3)) is part of the compilation process, and is not a general thing for the syntax 1:3 (as that's ambiguous).

In other words, if I remember correctly, lst[x:y:z] is a different syntactic construct from lst[x], as far as the Python compiler is concerned.


*The information in this post is based on my understanding and prior interaction with various methods in the CPython source code. I'm drawing some conclusions between the syntax, the compiler, and the compiled code that may not be valid.

like image 66
Green Cloak Guy Avatar answered Jan 02 '23 08:01

Green Cloak Guy