Что означает locals() ['_ [1]'] в Python?

Я увидел один код liner, который, как утверждается, удаляет дубликаты из последовательности:

u = [x for x in seq if x not in locals()['_[1]']]

Я пробовал этот код в ipython (с Python 2.7), он дал KeyError: '_[1]'

Значит ли ['_[1]'] что-то особенное в Python?

Ответ 1

locals()['_[1]'] - это способ доступа к текущему результату ссылки на список (или генератор) в этом понимании списка.

Это довольно зло, но может привести к смешным результатам:

>> [list(locals()['_[1]']) for x in range(3)]
[[], [[]], [[], [[]]]]

Подробнее см.: the-secret-name-of-list-comprehensions.

Ответ 2

Это временное имя, используемое в понимании списка Python 2.6 и ранее. Python 2.7 и Python 3.x исправили эту бородавку: создаваемый список больше не доступен до завершения создания.

Или, короче говоря, это была деталь реализации, на которую никто никогда не должен был полагаться.

Здесь вы можете видеть, что Python 2.7 оставляет locals() неизменным, в то время как Python 2.6 создает короткую живую временную:

Python 2.7.2 (default, Jan  5 2012, 16:24:09)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-51)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> def foo():
        t = [list(locals().keys()) for x in range(1) ]
        print(locals())
        print(t[0])

>>> foo()
{'x': 0, 't': [['x']]}
['x']
>>>

Python 2.6.7 (r267:88850, Jan  5 2012, 16:18:48)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-51)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> def foo():
        t = [list(locals().keys()) for x in range(1) ]
        print(locals())
        print(t[0])

>>> foo()
{'x': 0, 't': [['_[1]', 'x']]}
['_[1]', 'x']
>>>

Python 3.x вводит новые временные временные исключения для списка, называемые .0. Не поддавайтесь соблазну использовать это для чего угодно. Также полное представление списка выполняется в отдельном пространстве имен, поэтому переменные цикла не доступны вне цикла:

Python 3.2 (r32:88445, Jan  5 2012, 16:29:57)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-51)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> def foo():
        t = [list(locals().keys()) for x in range(1) ]
        print(locals())
        print(t[0])

>>> foo()
{'t': [['.0', 'x']]}
['.0', 'x']

Ответ 3

Ничего себе! Этот наглый загадочный код. Взял немного исследований, чтобы найти ответ.

В основном понимание списка - это создание нового списка. Он называет этот временный список _[1]. Часть locals() просто использует словарь locals() для поиска этого имени, поскольку оно недоступно в противном случае. Так что строка говорит...

[x for x in seq if x not in this_list]

Cryptic.

Найденная информация об этом здесь

Ответ 4

locals() из документов Python:

Обновить и вернуть словарь, представляющий текущую таблицу локальных символов. Свободные переменные возвращаются locals(), когда они вызываются в функциональных блоках, но не в блоках классов.

Я не понимаю, почему locals() используется в этом одном вкладыше, возможно, он не является общим, как вы хотите.

Если вы пытаетесь удалить дубликаты из списка, я думаю, что лучший выбор - преобразовать его в set:

In [2]: l = [1,1,3,4,2,4,6]
In [4]: set(l)
Out[4]: set([1, 2, 3, 4, 6])

Если вам нужен список еще раз:

In [5]: list(set(l))
Out[5]: [1, 2, 3, 4, 6]