Что означает это утверждение Python? - программирование
Подтвердить что ты не робот

Что означает это утверждение Python?

Я пишу парсер, и в процессе его отладки я обнаружил, что, по-видимому, это законный Python:

for []    in [[]]: print 0

и так далее (!):

for [][:] in [[]]: print 0

Я не обвиняю парсер в недоумении... Мне трудно понять, как его интерпретировать!

Что именно означает этот оператор?

4b9b3361

Ответ 1

В терминах выполнения: ничего.

Цикл for сам зацикливается на пустой список, поэтому никакие итерации не будут выполняться.

И это хорошо, потому что for [] означает: присваивать каждой записи в цикле 0 переменным. Последняя часть, вероятно, вас озадачивает.

Заявление является законным, поскольку целевой токен token_list позволяет присваивать значения в последовательности одинаковой последовательности имен переменных; мы вызываем эту распаковку. Ниже приведены более полезные примеры целевых списков при назначении и удалении:

(a, b, c) = range(3)
del a, b, c

Вы можете сделать то же самое в цикле for:

nested = [[1,2,3], [4,5,6]]
for a, b, c in nested:
    print nested

Вы можете использовать как кортежи, так и списки для токена target_list, это тоже законно:

[a, b] = (1, 2)

Однако в Python список может быть пустым. Таким образом, следующее юридическое, однако нечувственное:

[] = []

и, наконец, так:

nested_empty = [[], [], []]
for [] in nested_empty:
    pass

Больше удовольствия с целевыми списками:

[][:] = [1, 2, 3]

Теперь левая сторона использует срез в присваивании. Из документации:

Если цель является срезом: оценивается основное выражение в ссылке. Он должен давать изменяемый объект последовательности (например, список). Назначенный объект должен быть объектом последовательности того же типа. Затем оцениваются нижние и верхние граничные выражения, если они присутствуют; значения по умолчанию равны нулю и длина последовательности. Оценки должны оцениваться (малыми) целыми числами. Если какая-либо граница отрицательна, к ней добавляется длина последовательности. Результирующие границы ограничены, чтобы лежать между нулем и длиной последовательностей включительно. Наконец, объекту последовательности предлагается заменить срез на элементы назначенной последовательности. Длина среза может отличаться от длины назначенной последовательности, тем самым изменяя длину целевой последовательности, если объект разрешает ее.

Итак, здесь мы больше не используем распаковку кортежа; вместо этого вместо левой части списка мы заменяем правый список. Но поскольку в нашем примере левый список является анонимным списком, полученный измененный список снова теряется.

Но поскольку такое присваивание также является законным в цикле for, следующим является юридический синтаксис, хотя и довольно нечувственный:

for [][:] in [range(i) for i in range(10)]: print 0

Ответ 2

for [] in [[]]: print 0

он эквивалентен:

In [44]: for [x,y] in [[1,2],[3,4],[5,6]]: # or even (x,y) will work
    print x,y
   ....:     
   ....:     
1 2
3 4
5 6

но первый ожидает, что no value не будет возвращено из списка, i, e значения внутри списка либо пусты, либо их len() есть 0.

Вы не можете использовать () там, где это недействительно.

потому что в python вы можете назначить alss следующим образом:

In [56]: x,y=[1,2]      #this means that the expression on RHS should return two values
                        # (x,y)=[1,2] or x,y=(1,2) or (x,y)=(1,2) all are valid

In [57]: x
Out[57]: 1

In [58]: y
Out[58]: 2


In [62]: x,y='ab'     #assign a to x and b to y

In [63]: x
Out[63]: 'a'

In [64]: y
Out[64]: 'b'

Ответ 3

Вот мое лучшее предположение:

for [] in [[]] означает "для каждого экземпляра [] (пустого объекта списка) в этом списке [[]] (список с ровно одним элементом, который является пустым объектом списка), print 0.

Во втором случае, я думаю, [:] просто вызовет slice() со всеми значениями по умолчанию, которые просто возьмут кусочек всего списка. Внутренне, что может что-то сделать, например, сделать копию объекта списка, но эффект в этом случае должен быть одинаковым.

Ответ 4

Структура for..in описана в руководстве Python

http://docs.python.org/reference/compound_stmts.html#the-for-statement

Вы можете иметь несколько переменных слева от ключевого слова in

for [i,j] in [(1,2),(3,4),(5,6)]:
  print i, j

for [i,j] in [[1,2],[3,4],[5,6]]:
  print i, j

В руководстве сказано, что оно интерпретируется как

i,j = (1,2)

для первой итерации и т.д. Таким образом, у вас может быть пустой список переменных, так как список итераций имеет пустой список как только элемент. Этот цикл будет печатать 0 один раз.

Парсер, который вы читаете, автоматически генерируется? Этот вид заявления может быть создан нечеловеческим источником. Я не вижу в этом цели.

Ответ 5

for []    in [[]]: print 0

означает, что для каждого пустого iterables в [[]], который является списком, который содержит пустой список, напечатайте 0. Он не только ограничен списками, но и все iterables могут быть помещены в это. Например, вы можете попробовать:

# empty list, empty tuple, empty string, empty unicode
for [] in [[], (), '', unicode()]: print 0

и он будет печатать 0 четыре раза.

[] [:] совпадает с []. Он вернет пустой список, поэтому мой ответ будет таким же, как и выше.

Ответ 6

Предположим, у вас есть список кортежей, который выглядит так:

L = [(1,2), (3,4), (5,6)]

Предположим, вы хотите напечатать эти кортежи каким-то особым образом:

for tup in L:
    a = tup[0]
    b = tup[1]
    if a<b:
        print a,b
    else:
        print b,a

Но назначение явно a и b содержимого tup довольно утомительно. Поэтому вы можете сделать это:

for tup in L:
    a,b = tup
    if a<b:
        print a,b
    else:
        print b,a

Но вы могли бы сделать это еще менее утомительным:

for (a,b) in L: # you could also do "for [a,b] in L"
    if a<b:
        print a,b
    else:
        print b,a

Здесь шаблон (a,b) совпадает с элементом, возвращаемым итерацией. При первом выполнении цикла for элемент, возвращаемый итерацией, равен (1,2), который получает шаблон, сопоставляемый с (a,b), поэтому присваивает 1 a и 2 - b

Теперь, в первом примере, вы повторяете список, содержащий пустой список. Это означает, что вы пытаетесь напечатать как можно больше 0, поскольку в этом списке есть []. Но это немного сложнее, чем это:

Когда вы пытаетесь сопоставить шаблон, как в моем третьем примере, python выполняет итерацию над списком (или кортежем) переменных и элементом, возвращаемым итератором, одновременно присваивая значения по мере их поступления. Поэтому, когда ваш шаблон не содержит переменных, тогда элемент, который вы пытаетесь сопоставить с шаблоном, также должен быть пустым (и повторяемым). Это объясняет следующее поведение:

>>> for i in 5: print i
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable

>>> for [] in [[], 5]: print 0
... 
0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable

... и это тоже:

>>> x,y = (2,5,3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack

>>> for [] in [[], [5]]: print 0
... 
0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack

Теперь, что касается вашего второго примера, операция [:] в основном создает копию списка, на который он вызвал, так что изменение исходного списка не изменяет копию и наоборот:

>>> L = [1,2,3]
>>> M = L
>>> M[0] = 'a'
>>> print L[0]
'a'

>>> L = [1,2,3]
>>> M = L[:]
>>> M[0] = 'a'
>>> print L[0]
1

Поэтому, когда вы вызываете [][:], все, что вы делаете, создает новый пустой список, который работает так же, как мое объяснение для вашего первого примера