Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

binding local variables in python

Tags:

python

lisp

I wonder if there is a good way to bind local variables in python. Most of my work involves cobbling together short data or text processing scripts with a series of expressions (when python permits), so defining object classes (to use as namespaces) and instantiating them seems a bit much.

So what I had in mind was something like in (common) lisp, where you could do something like

(setq data '(1 2 3))
(setq output 
      (let ( (x (nth 2 data)) )
       x + x))

In python, the best I could come up with is

data = [1,2,3]
output = ((lambda x: x + x)
          (data[2]))

These are, of course, very simple examples but might there be something that is as scalable as let or let* in lisp? Are defining classes the best way to go to create a local namespace?...(but feels a little less interactive that way)

Edit: So to further explain the intention (my apologies for vagueness), I want to reduce the use of global variables. So in the case above, I meant to use the extraction operator as a general case of any type of operation that might not want to be repeated. For instance, one might write either

output = data[2] + data[2]

or

x = data[2]
output = x + x
del x

to accomplish the same result. In essence, if the desired operation on 'data' is more complicated then getting the second item, I wouldn't want to type it out multiple times, or let the computer compute the value of the same expression more times than necessary. So in most cases one would assign the result of the operation, in this case, data[2], or operator.itemgetter(2)(data), to some variable in the global space, but I have an aversion to leaving variables around in the global space if they were only necessary to store intermediate values in a computation... hence the use of the 'del' command immediately afterwards. Defining a local environment or namespace and binding intermediate results to local variables would be an ideal alternative.

like image 697
hatmatrix Avatar asked Feb 28 '23 05:02

hatmatrix


2 Answers

I can only second Lennart and Daniel - Python is not Lisp, and trying to write language X into language Y is usually inefficient and frustrating at best.

First point: your example code

data = [1,2,3]
output = ((lambda x: x + x)
          (data[2]))

would be much more readable as:

data = [1, 2, 3]
output = (lambda x=data[2] : x +x)()

but anyway, in this concrete case, using a lambda is total overkill, overcomplexificated, and mostly inefficient. A braindead

output = data[2] + data[2]

would JustWork(tm) !-)

Now wrt/ to local bindings / namespaces, the usual solution is to use... functions - eventually nested. While 100% object (as in "everything is an object"), Python is not pure object, and plain functions are just fine. FWIW, even for "scripts", you should put your logic in a function then call it - function's local namespace access is faster than "global" (really: module level) namespace access. The canonical pattern is

import whatever

def some_func(args):
    code_here

def some_other_func(args)
    code_here

def main(args):
    parse_args
    some_func(something)
    some_other_func(something_else)
    return some_exit_code

if __name__ == '__main__'
    import sys
    sys.exit(main(sys.argv))         

Note also that nested functions can also access the enclosing namespace, ie

def main():
    data = [1, 2, 3]
    def foo():
       x = data[2]
       return x + x
    print foo()
    data = [4, 5, 6]
    print foo()
    # if you want the nested function to close over its arguments:
    def bar(data=data):
       x = data[2]
       return x + x
    print bar()
    data = [7, 8, 9]
    print bar()

HTH

like image 190
bruno desthuilliers Avatar answered Mar 02 '23 17:03

bruno desthuilliers


It's a bit unclear what you are asking, bit I'll try to answer anyway:

You bind variables to names with = in Python. So your data = [1,2,3] binds the list [1,2,3] to the name data.

You can create local namespaces with classes and functions/methods.

The closest you get so something as powerful as let is probably def and lambda. Python is (despite where some people try to tell you) not Lisp, and not particularly functional, so you will have to adapt your mindset a bit.

Update: Ah, I see what you mean now.

All variables are pretty much local in Python. The nearest you get to global variables are variables defined in module space, because you can access them with from <module> import <variable>. You also can access them from wherever in the module, but not modify them (unless you say that you want to modify them with the global keyword. Anything you define in a function/method or class definition, will only be accessible from that namespace.

So in short: you don't have to worry about the things you worry about now. Python takes care of it for you. :)

like image 25
Lennart Regebro Avatar answered Mar 02 '23 17:03

Lennart Regebro