В Python, почему выражение лямбда ссылается на определяемую переменную, но не на список?

Это скорее любопытство, чем что-либо, но я только заметил следующее. Если я определяю самореферентную лямбду, я могу сделать это легко:

>>> f = lambda: f >>> f() is f True 

Но если я определяю список со ссылками, я должен сделать это более чем в одном утверждении:

 >>> a = [a] Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'a' is not defined >>> a = [] >>> a.append(a) >>> a[0] is a True >>> a [[...]] 

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

 >>> class Node(object): ... def __init__(self, next_node): ... self.next = next_node ... >>> n = Node(n) Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'n' is not defined 

Вместо этого вы должны сделать это в двух утверждениях:

 >>> n = Node(None) >>> n.next = n >>> n is n.next True 

Кто-нибудь знает, что такое философия, лежащая в основе этой разницы? Я понимаю, что рекурсивная лямбда используется гораздо чаще, и, следовательно, поддержка самореференции важна для лямбда, но почему бы не разрешить ее для каких-либо заданий?

EDIT: ответы ниже объясняют это довольно хорошо. Причина в том, что переменные в lambdas в Python оцениваются каждый раз, когда вызывается лямбда, а не когда она определена. В этом смысле они точно такие же, как функции, определенные с помощью def . Я написал следующий бит кода, чтобы поэкспериментировать с тем, как это работает, как с функциями lambdas, так и def если это может помочь прояснить его для всех.

 >>> f = lambda: f >>> f() is f True >>> g = f >>> f = "something else" >>> g() 'something else' >>> f = "hello" >>> g() 'hello' >>> f = g >>> g() is f True >>> def f(): ... print(f) ... >>> f() <function f at 0x10d125560> >>> g = f >>> g() <function f at 0x10d125560> >>> f = "test" >>> g() test >>> f = "something else" >>> g() something else 

3 Solutions collect form web for “В Python, почему выражение лямбда ссылается на определяемую переменную, но не на список?”

Выражение внутри лямбда оценивается при вызове функции, а не тогда, когда она определена.

Другими словами, Python не будет оценивать f внутри вашей лямбды, пока вы ее не назовете. И к тому времени f уже определен в текущей области (это сама лямбда). Следовательно, No NameError не NameError .


Обратите внимание, что это не относится к такой строке:

 a = [a] 

Когда Python интерпретирует этот тип строки (известный как оператор присваивания), он будет оценивать выражение справа от = немедленно. Более того, NameError будет поднят для любого имени, используемого справа, которое не определено в текущей области.

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

Другими словами, другой способ сделать это:

 def f(): return f 

Но вы правы, что не можете сделать это в выражении, потому что def – это оператор, поэтому он не может использоваться в выражении.

Мы можем видеть, когда мы разбираем лямбда-функцию (это идентичный вывод в Python 2.6 и 3.3)

 >>> import dis >>> f = lambda: f >>> dis.dis(f) 1 0 LOAD_GLOBAL 0 (f) 3 RETURN_VALUE 

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

 >>> f is f() True 

Но когда мы делаем:

 >>> a = [a] 

У нас есть ошибка (если a ранее не определено), и если мы разобраем реализацию Python.

 >>> def foo(): ... a = [a] ... >>> dis.dis(foo) 2 0 LOAD_FAST 0 (a) 3 BUILD_LIST 1 6 STORE_FAST 0 (a) 9 LOAD_CONST 0 (None) 12 RETURN_VALUE 

мы видим, что мы пытаемся загрузить a прежде чем мы его сохранили.

  • appcfg.py показывает, что вы должны войти в систему как администратор
  • Создание экземпляра класса с переменной в Python
  • Чтение и выполнение математического выражения в Python
  • Отдельные слова в списке, а затем печать позиций этих слов
  • Количество чисел вхождения символа в строке
  • Есть ли какой-либо умный способ комбинировать перекрывающиеся пути в python?
  • Что такое значок галочки рядом с моим проектом в PyCharm?
  • Как я могу читать две строки из файла за раз, используя python
  •  
    Interesting Posts for Van-Lav

    Зачем загружать статические файлы для каждого шаблона, даже если он расширяется?

    Чтение данных в массив numpy из текстового файла

    Совместное использование соединения базы данных Oracle между одновременными задачами Celery

    Почему вычисление numpy не влияет на блокировку глобального интерпретатора?

    Синтаксис в Python (.T)

    pyspark: Создать столбцы MapType из существующих столбцов

    установить мультииндекс существующего фрейма данных в пандах

    Python – Как PYTHONPATH со сложной структурой каталогов?

    Может ли временный файл flymake быть создан во временном каталоге системы?

    Как предотвратить hasattr от извлечения самого значения атрибута

    Как рекурсивно запрашивать в django эффективно?

    Сортировка списка Python зависит от того, находятся ли элементы в другом списке

    Изменение списка во время итерации по нему – почему бы и нет?

    python копирует файлы в сетевое расположение в Windows без сопоставления диска

    bcrypt.checkpw возвращает TypeError: объекты Unicode должны быть закодированы перед проверкой

    Python - лучший язык программирования в мире.