Question

In python what is the equivalent of the quote operator? I am finding the need to delay evaluation. For example, suppose in the following lisp psuedocode I have:

a = '(func, 'g)
g = something
(eval a)

What I am doing is deferring evaluation of g till a later time. This is necessary because I want to define g later. What is the equivalent idea of this psuedocode in python?

Was it helpful?

Solution

a = lambda: func(g)
g = something
a()

This isn't quite the most literal translation - the most literal translation would use a string and eval - but it's probably the best fit. Quoting probably isn't what you wanted in Lisp anyway; you probably wanted to delay something or create a lambda. Note that func and g are closure variables in the lambda function, rather than symbols, so if you call a from an environment with different bindings for func or g, it'll still use the variables from a's environment of definition.

OTHER TIPS

Using eval for delaying evaluation is bad, both in Lisp and Python.

in Python, and in Lisp, you can delay evaluation using a closure:

def print_it(x):
    def f():
        print g(x)
    return f

f = print_it(42)

def g(x):
   return x * x

f()

Please note that what is captured in a closure is not the value of a variable, but the variable itself and this is sometimes surprising:

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

to solve this problem (that can also be present in Common Lisp) you may see things like:

for x in range(10):
    def g(x = x):
        print x
    fa.append(g)

or (in CL) things like

(let ((a a))
  (lambda () (print a)))

Python also has a lambda special form for anonymous functions, but they are limited to one single expression and cannot contain any statement. A locally def-ined function instead is a regular function without any limitations.

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"))

Finally Python 2.x has a syntax limitation and closed-over variables are read-only because if there is an assignment (or augmented-assignment) in a function there are only two possibilities:

  1. The variable is a global (and has been previously declared so with global x)
  2. The variable is a local

and in particular it's ruled out that a variable being assigned could be a local of an enclosing function scope.

Python 3.x removed this limitation by providing a new possible declaration nonlocal x and now the famous adder example can be implemented as

def adder(x):
    def f(y):
        nonlocal x
        x += y
        return x
    return f
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top