Python эквивалент цитаты в LISP
В Python, что эквивалентно оператору кавычки? Я нахожу необходимость отложить оценку. Например, предположим, что в следующем lisp psuedocode у меня есть:
a = '(func, 'g)
g = something
(eval a)
Что я делаю, так это отложенную оценку g
до более позднего времени. Это необходимо, потому что я хочу определить g
потом. Какова эквивалентная идея этого псевдокода в Python?
2 ответа
a = lambda: func(g)
g = something
a()
Это не самый буквальный перевод - самый буквальный перевод будет использовать строку и eval
- но это, вероятно, лучше всего подходит. Цитировать, вероятно, совсем не то, что вы хотели в Лиспе; Вы, вероятно, хотели delay
что-то или создать lambda
, Обратите внимание, что func
а также g
переменные замыкания в lambda
функция, а не символы, так что если вы звоните a
из среды с разными привязками для func
или же g
, он все еще будет использовать переменные из a
Среда определения.
С помощью eval
задерживать оценку плохо, как в Lisp, так и в Python.
в Python и в Lisp вы можете отложить оценку, используя замыкание:
def print_it(x):
def f():
print g(x)
return f
f = print_it(42)
def g(x):
return x * x
f()
Обратите внимание, что в замыкании фиксируется не значение переменной, а сама переменная, и это иногда удивляет:
fa = []
for x in range(10):
def g():
print x
fa.append(g)
for f in fa:
f() # all of them will print 9
x = 42
fa[0]() # the output will be 42
Для решения этой проблемы (которая также может присутствовать в Common Lisp) вы можете увидеть такие вещи, как:
for x in range(10):
def g(x = x):
print x
fa.append(g)
или (в CL) такие вещи, как
(let ((a a))
(lambda () (print a)))
Python также имеет lambda
специальная форма для анонимных функций, но они ограничены одним выражением и не могут содержать никаких утверждений. Локально def
Функция вместо этого является обычной функцией без каких-либо ограничений.
for x in range(10):
# print is a statement in Python 2.x and cannot be in a lambda
fa.append(lambda x=x: sys.stdout.write(str(x) + "\n"))
Наконец, Python 2.x имеет синтаксическое ограничение, а закрытые переменные доступны только для чтения, потому что если в функции есть присваивание (или расширенное присваивание), есть только две возможности:
- Переменная является глобальной (и ранее была объявлена
global x
) - Переменная является локальной
и, в частности, исключено, что назначаемая переменная может быть локальной в области действия включающей функции.
Python 3.x снял это ограничение, предоставив новое возможное объявление nonlocal x
а теперь знаменитый adder
Пример может быть реализован как
def adder(x):
def f(y):
nonlocal x
x += y
return x
return f