binding local variables in python - python

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.

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

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. :)

You could combine a function decorator and default parameters to get something like let and block scoped variables:
def let(func):
return func()
data = [1,2,3]
#let
def output(x=data[2]):
return x + x
print(output) # 6
# or if a single expression is enough:
output = let(lambda x=data[2]: x+x)
But this isn't a popular idiom in Python so I advise you avoid it to make your code easier to understand for others. Just use regular local variables:
data = [1,2,3]
x = data[2]
output = x + x
If this becomes a real problem it's a good sign you are trying to do too much in a single function.

Not really knowing Lisp, I can't see what you're trying to do here. But I would say that in general you should not try to write Python as if it were Lisp, or indeed any language as if it were any other language. I've been programming in Python for five years and I've never seen a need to do what you're trying above.
Can you give an example of a use case for the above - what are you actually trying to do, in terms of the end result? Maybe then we can advise you on the best way to do it in Python, rather than Lisp.

Related

What will be the values of the lambda var in the following function syntax? [duplicate]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I'm trying to figure out Python lambdas. Is lambda one of those "interesting" language items that in real life should be forgotten?
I'm sure there are some edge cases where it might be needed, but given the obscurity of it, the potential of it being redefined in future releases (my assumption based on the various definitions of it) and the reduced coding clarity - should it be avoided?
This reminds me of overflowing (buffer overflow) of C types - pointing to the top variable and overloading to set the other field values. It feels like sort of a techie showmanship but maintenance coder nightmare.
Are you talking about lambda expressions? Like
lambda x: x**2 + 2*x - 5
Those things are actually quite useful. Python supports a style of programming called functional programming where you can pass functions to other functions to do stuff. Example:
mult3 = filter(lambda x: x % 3 == 0, [1, 2, 3, 4, 5, 6, 7, 8, 9])
sets mult3 to [3, 6, 9], those elements of the original list that are multiples of 3. This is shorter (and, one could argue, clearer) than
def filterfunc(x):
return x % 3 == 0
mult3 = filter(filterfunc, [1, 2, 3, 4, 5, 6, 7, 8, 9])
Of course, in this particular case, you could do the same thing as a list comprehension:
mult3 = [x for x in [1, 2, 3, 4, 5, 6, 7, 8, 9] if x % 3 == 0]
(or even as range(3,10,3)), but there are many other, more sophisticated use cases where you can't use a list comprehension and a lambda function may be the shortest way to write something out.
Returning a function from another function
>>> def transform(n):
... return lambda x: x + n
...
>>> f = transform(3)
>>> f(4)
7
This is often used to create function wrappers, such as Python's decorators.
Combining elements of an iterable sequence with reduce()
>>> reduce(lambda a, b: '{}, {}'.format(a, b), [1, 2, 3, 4, 5, 6, 7, 8, 9])
'1, 2, 3, 4, 5, 6, 7, 8, 9'
Sorting by an alternate key
>>> sorted([1, 2, 3, 4, 5, 6, 7, 8, 9], key=lambda x: abs(5-x))
[5, 4, 6, 3, 7, 2, 8, 1, 9]
I use lambda functions on a regular basis. It took me a while to get used to them, but eventually I came to understand that they're a very valuable part of the language.
lambda is just a fancy way of saying function. Other than its name, there is nothing obscure, intimidating or cryptic about it. When you read the following line, replace lambda by function in your mind:
>>> f = lambda x: x + 1
>>> f(3)
4
It just defines a function of x. Some other languages, like R, say it explicitly:
> f = function(x) { x + 1 }
> f(3)
4
You see? It's one of the most natural things to do in programming.
The two-line summary:
Closures: Very useful. Learn them, use them, love them.
Python's lambda keyword: unnecessary, occasionally useful. If you find yourself doing anything remotely complex with it, put it away and define a real function.
A lambda is part of a very important abstraction mechanism which deals with higher order functions. To get proper understanding of its value, please watch high quality lessons from Abelson and Sussman, and read the book SICP
These are relevant issues in modern software business, and becoming ever more popular.
I doubt lambda will go away.
See Guido's post about finally giving up trying to remove it. Also see an outline of the conflict.
You might check out this post for more of a history about the deal behind Python's functional features:
http://python-history.blogspot.com/2009/04/origins-of-pythons-functional-features.html
Curiously, the map, filter, and reduce functions that originally motivated the introduction of lambda and other functional features have to a large extent been superseded by list comprehensions and generator expressions. In fact, the reduce function was removed from list of builtin functions in Python 3.0. (However, it's not necessary to send in complaints about the removal of lambda, map or filter: they are staying. :-)
My own two cents: Rarely is lambda worth it as far as clarity goes. Generally there is a more clear solution that doesn't include lambda.
lambdas are extremely useful in GUI programming. For example, lets say you're creating a group of buttons and you want to use a single paramaterized callback rather than a unique callback per button. Lambda lets you accomplish that with ease:
for value in ["one","two","three"]:
b = tk.Button(label=value, command=lambda arg=value: my_callback(arg))
b.pack()
(Note: although this question is specifically asking about lambda, you can also use functools.partial to get the same type of result)
The alternative is to create a separate callback for each button which can lead to duplicated code.
In Python, lambda is just a way of defining functions inline,
a = lambda x: x + 1
print a(1)
and..
def a(x): return x + 1
print a(1)
..are the exact same.
There is nothing you can do with lambda which you cannot do with a regular function—in Python functions are an object just like anything else, and lambdas simply define a function:
>>> a = lambda x: x + 1
>>> type(a)
<type 'function'>
I honestly think the lambda keyword is redundant in Python—I have never had the need to use them (or seen one used where a regular function, a list-comprehension or one of the many builtin functions could have been better used instead)
For a completely random example, from the article "Python’s lambda is broken!":
To see how lambda is broken, try generating a list of functions fs=[f0,...,f9] where fi(n)=i+n. First attempt:
>>> fs = [(lambda n: i + n) for i in range(10)]
>>> fs[3](4)
13
I would argue, even if that did work, it's horribly and "unpythonic", the same functionality could be written in countless other ways, for example:
>>> n = 4
>>> [i + n for i in range(10)]
[4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
Yes, it's not the same, but I have never seen a cause where generating a group of lambda functions in a list has been required. It might make sense in other languages, but Python is not Haskell (or Lisp, or ...)
Please note that we can use lambda and still achieve the desired
results in this way :
>>> fs = [(lambda n,i=i: i + n) for i in range(10)]
>>> fs[3](4)
7
Edit:
There are a few cases where lambda is useful, for example it's often convenient when connecting up signals in PyQt applications, like this:
w = PyQt4.QtGui.QLineEdit()
w.textChanged.connect(lambda event: dothing())
Just doing w.textChanged.connect(dothing) would call the dothing method with an extra event argument and cause an error. Using the lambda means we can tidily drop the argument without having to define a wrapping function.
I find lambda useful for a list of functions that do the same, but for different circumstances.
Like the Mozilla plural rules:
plural_rules = [
lambda n: 'all',
lambda n: 'singular' if n == 1 else 'plural',
lambda n: 'singular' if 0 <= n <= 1 else 'plural',
...
]
# Call plural rule #1 with argument 4 to find out which sentence form to use.
plural_rule[1](4) # returns 'plural'
If you'd have to define a function for all of those you'd go mad by the end of it.
Also, it wouldn't be nice with function names like plural_rule_1, plural_rule_2, etc. And you'd need to eval() it when you're depending on a variable function id.
Pretty much anything you can do with lambda you can do better with either named functions or list and generator expressions.
Consequently, for the most part you should just one of those in basically any situation (except maybe for scratch code written in the interactive interpreter).
I've been using Python for a few years and I've never run in to a case where I've needed lambda. Really, as the tutorial states, it's just for syntactic sugar.
Lambda function it's a non-bureaucratic way to create a function.
That's it. For example, let's supose you have your main function and need to square values. Let's see the traditional way and the lambda way to do this:
Traditional way:
def main():
...
...
y = square(some_number)
...
return something
def square(x):
return x**2
The lambda way:
def main():
...
square = lambda x: x**2
y = square(some_number)
return something
See the difference?
Lambda functions go very well with lists, like lists comprehensions or map. In fact, list comprehension it's a "pythonic" way to express yourself using lambda. Ex:
>>>a = [1,2,3,4]
>>>[x**2 for x in a]
[1,4,9,16]
Let's see what each elements of the syntax means:
[] : "Give me a list"
x**2 : "using this new-born function"
for x in a: "into each element in a"
That's convenient uh? Creating functions like this. Let's rewrite it using lambda:
>>> square = lambda x: x**2
>>> [square(s) for x in a]
[1,4,9,16]
Now let's use map, which is the same thing, but more language-neutral. Maps takes 2 arguments:
(i) one function
(ii) an iterable
And gives you a list where each element it's the function applied to each element of the iterable.
So, using map we would have:
>>> a = [1,2,3,4]
>>> squared_list = map(lambda x: x**2, a)
If you master lambdas and mapping, you will have a great power to manipulate data and in a concise way. Lambda functions are neither obscure nor take away code clarity. Don't confuse something hard with something new. Once you start using them, you will find it very clear.
I can't speak to python's particular implementation of lambda, but in general lambda functions are really handy. They're a core technique (maybe even THE technique) of functional programming, and they're also very useuful in object-oriented programs. For certain types of problems, they're the best solution, so certainly shouldn't be forgotten!
I suggest you read up on closures and the map function (that links to python docs, but it exists in nearly every language that supports functional constructs) to see why it's useful.
One of the nice things about lambda that's in my opinion understated is that it's way of deferring an evaluation for simple forms till the value is needed. Let me explain.
Many library routines are implemented so that they allow certain parameters to be callables (of whom lambda is one). The idea is that the actual value will be computed only at the time when it's going to be used (rather that when it's called). An (contrived) example might help to illustrate the point. Suppose you have a routine which which was going to do log a given timestamp. You want the routine to use the current time minus 30 minutes. You'd call it like so
log_timestamp(datetime.datetime.now() - datetime.timedelta(minutes = 30))
Now suppose the actual function is going to be called only when a certain event occurs and you want the timestamp to be computed only at that time. You can do this like so
log_timestamp(lambda : datetime.datetime.now() - datetime.timedelta(minutes = 30))
Assuming the log_timestamp can handle callables like this, it will evaluate this when it needs it and you'll get the timestamp at that time.
There are of course alternate ways to do this (using the operator module for example) but I hope I've conveyed the point.
Update: Here is a slightly more concrete real world example.
Update 2: I think this is an example of what is called a thunk.
As stated above, the lambda operator in Python defines an anonymous function, and in Python functions are closures. It is important not to confuse the concept of closures with the operator lambda, which is merely syntactic methadone for them.
When I started in Python a few years ago, I used lambdas a lot, thinking they were cool, along with list comprehensions. However, I wrote and have to maintain a big website written in Python, with on the order of several thousand function points. I've learnt from experience that lambdas might be OK to prototype things with, but offer nothing over inline functions (named closures) except for saving a few key-stokes, or sometimes not.
Basically this boils down to several points:
it is easier to read software that is explicitly written using meaningful names. Anonymous closures by definition cannot have a meaningful name, as they have no name. This brevity seems, for some reason, to also infect lambda parameters, hence we often see examples like lambda x: x+1
it is easier to reuse named closures, as they can be referred to by name more than once, when there is a name to refer to them by.
it is easier to debug code that is using named closures instead of lambdas, because the name will appear in tracebacks, and around the error.
That's enough reason to round them up and convert them to named closures. However, I hold two other grudges against anonymous closures.
The first grudge is simply that they are just another unnecessary keyword cluttering up the language.
The second grudge is deeper and on the paradigm level, i.e. I do not like that they promote a functional-programming style, because that style is less flexible than the message passing, object oriented or procedural styles, because the lambda calculus is not Turing-complete (luckily in Python, we can still break out of that restriction even inside a lambda). The reasons I feel lambdas promote this style are:
There is an implicit return, i.e. they seem like they 'should' be functions.
They are an alternative state-hiding mechanism to another, more explicit, more readable, more reusable and more general mechanism: methods.
I try hard to write lambda-free Python, and remove lambdas on sight. I think Python would be a slightly better language without lambdas, but that's just my opinion.
Lambdas are actually very powerful constructs that stem from ideas in functional programming, and it is something that by no means will be easily revised, redefined or removed in the near future of Python. They help you write code that is more powerful as it allows you to pass functions as parameters, thus the idea of functions as first-class citizens.
Lambdas do tend to get confusing, but once a solid understanding is obtained, you can write clean elegant code like this:
squared = map(lambda x: x*x, [1, 2, 3, 4, 5])
The above line of code returns a list of the squares of the numbers in the list. Ofcourse, you could also do it like:
def square(x):
return x*x
squared = map(square, [1, 2, 3, 4, 5])
It is obvious the former code is shorter, and this is especially true if you intend to use the map function (or any similar function that takes a function as a parameter) in only one place. This also makes the code more intuitive and elegant.
Also, as #David Zaslavsky mentioned in his answer, list comprehensions are not always the way to go especially if your list has to get values from some obscure mathematical way.
From a more practical standpoint, one of the biggest advantages of lambdas for me recently has been in GUI and event-driven programming. If you take a look at callbacks in Tkinter, all they take as arguments are the event that triggered them. E.g.
def define_bindings(widget):
widget.bind("<Button-1>", do-something-cool)
def do-something-cool(event):
#Your code to execute on the event trigger
Now what if you had some arguments to pass? Something as simple as passing 2 arguments to store the coordinates of a mouse-click. You can easily do it like this:
def main():
# define widgets and other imp stuff
x, y = None, None
widget.bind("<Button-1>", lambda event: do-something-cool(x, y))
def do-something-cool(event, x, y):
x = event.x
y = event.y
#Do other cool stuff
Now you can argue that this can be done using global variables, but do you really want to bang your head worrying about memory management and leakage especially if the global variable will just be used in one particular place? That would be just poor programming style.
In short, lambdas are awesome and should never be underestimated. Python lambdas are not the same as LISP lambdas though (which are more powerful), but you can really do a lot of magical stuff with them.
Lambdas are deeply linked to functional programming style in general. The idea that you can solve problems by applying a function to some data, and merging the results, is what google uses to implement most of its algorithms.
Programs written in functional programming style, are easily parallelized and hence are becoming more and more important with modern multi-core machines.
So in short, NO you should not forget them.
First congrats that managed to figure out lambda. In my opinion this is really powerful construct to act with. The trend these days towards functional programming languages is surely an indicator that it neither should be avoided nor it will be redefined in the near future.
You just have to think a little bit different. I'm sure soon you will love it. But be careful if you deal only with python. Because the lambda is not a real closure, it is "broken" somehow: pythons lambda is broken
I'm just beginning Python and ran head first into Lambda- which took me a while to figure out.
Note that this isn't a condemnation of anything. Everybody has a different set of things that don't come easily.
Is lambda one of those 'interesting' language items that in real life should be forgotten?
No.
I'm sure there are some edge cases where it might be needed, but given the obscurity of it,
It's not obscure. The past 2 teams I've worked on, everybody used this feature all the time.
the potential of it being redefined in future releases (my assumption based on the various definitions of it)
I've seen no serious proposals to redefine it in Python, beyond fixing the closure semantics a few years ago.
and the reduced coding clarity - should it be avoided?
It's not less clear, if you're using it right. On the contrary, having more language constructs available increases clarity.
This reminds me of overflowing (buffer overflow) of C types - pointing to the top variable and overloading to set the other field values...sort of a techie showmanship but maintenance coder nightmare..
Lambda is like buffer overflow? Wow. I can't imagine how you're using lambda if you think it's a "maintenance nightmare".
A useful case for using lambdas is to improve the readability of long list comprehensions.
In this example loop_dic is short for clarity but imagine loop_dic being very long. If you would just use a plain value that includes i instead of the lambda version of that value you would get a NameError.
>>> lis = [{"name": "Peter"}, {"name": "Josef"}]
>>> loop_dic = lambda i: {"name": i["name"] + " Wallace" }
>>> new_lis = [loop_dic(i) for i in lis]
>>> new_lis
[{'name': 'Peter Wallace'}, {'name': 'Josef Wallace'}]
Instead of
>>> lis = [{"name": "Peter"}, {"name": "Josef"}]
>>> new_lis = [{"name": i["name"] + " Wallace"} for i in lis]
>>> new_lis
[{'name': 'Peter Wallace'}, {'name': 'Josef Wallace'}]
I use lambdas to avoid code duplication. It would make the function easily comprehensible
Eg:
def a_func()
...
if some_conditon:
...
call_some_big_func(arg1, arg2, arg3, arg4...)
else
...
call_some_big_func(arg1, arg2, arg3, arg4...)
I replace that with a temp lambda
def a_func()
...
call_big_f = lambda args_that_change: call_some_big_func(arg1, arg2, arg3, args_that_change)
if some_conditon:
...
call_big_f(argX)
else
...
call_big_f(argY)
I started reading David Mertz's book today 'Text Processing in Python.' While he has a fairly terse description of Lambda's the examples in the first chapter combined with the explanation in Appendix A made them jump off the page for me (finally) and all of a sudden I understood their value. That is not to say his explanation will work for you and I am still at the discovery stage so I will not attempt to add to these responses other than the following:
I am new to Python
I am new to OOP
Lambdas were a struggle for me
Now that I read Mertz, I think I get them and I see them as very useful as I think they allow a cleaner approach to programming.
He reproduces the Zen of Python, one line of which is Simple is better than complex. As a non-OOP programmer reading code with lambdas (and until last week list comprehensions) I have thought-This is simple?. I finally realized today that actually these features make the code much more readable, and understandable than the alternative-which is invariably a loop of some sort. I also realized that like financial statements-Python was not designed for the novice user, rather it is designed for the user that wants to get educated. I can't believe how powerful this language is. When it dawned on me (finally) the purpose and value of lambdas I wanted to rip up about 30 programs and start over putting in lambdas where appropriate.
I can give you an example where I actually needed lambda serious. I'm making a graphical program, where the use right clicks on a file and assigns it one of three options. It turns out that in Tkinter (the GUI interfacing program I'm writing this in), when someone presses a button, it can't be assigned to a command that takes in arguments. So if I chose one of the options and wanted the result of my choice to be:
print 'hi there'
Then no big deal. But what if I need my choice to have a particular detail. For example, if I choose choice A, it calls a function that takes in some argument that is dependent on the choice A, B or C, TKinter could not support this. Lamda was the only option to get around this actually...
I use it quite often, mainly as a null object or to partially bind parameters to a function.
Here are examples:
to implement null object pattern:
{
DATA_PACKET: self.handle_data_packets
NET_PACKET: self.handle_hardware_packets
}.get(packet_type, lambda x : None)(payload)
for parameter binding:
let say that I have the following API
def dump_hex(file, var)
# some code
pass
class X(object):
#...
def packet_received(data):
# some kind of preprocessing
self.callback(data)
#...
Then, when I wan't to quickly dump the recieved data to a file I do that:
dump_file = file('hex_dump.txt','w')
X.callback = lambda (x): dump_hex(dump_file, x)
...
dump_file.close()
I use lambda to create callbacks that include parameters. It's cleaner writing a lambda in one line than to write a method to perform the same functionality.
For example:
import imported.module
def func():
return lambda: imported.module.method("foo", "bar")
as opposed to:
import imported.module
def func():
def cb():
return imported.module.method("foo", "bar")
return cb
I'm a python beginner, so to getter a clear idea of lambda I compared it with a 'for' loop; in terms of efficiency.
Here's the code (python 2.7) -
import time
start = time.time() # Measure the time taken for execution
def first():
squares = map(lambda x: x**2, range(10))
# ^ Lambda
end = time.time()
elapsed = end - start
print elapsed + ' seconds'
return elapsed # gives 0.0 seconds
def second():
lst = []
for i in range(10):
lst.append(i**2)
# ^ a 'for' loop
end = time.time()
elapsed = end - start
print elapsed + ' seconds'
return elapsed # gives 0.0019998550415 seconds.
print abs(second() - first()) # Gives 0.0019998550415 seconds!(duh)
Lambda is a procedure constructor. You can synthesize programs at run-time, although Python's lambda is not very powerful. Note that few people understand that kind of programming.

Why are assignments not allowed in Python's `lambda` expressions?

This is not a duplicate of Assignment inside lambda expression in Python, i.e., I'm not asking how to trick Python into assigning in a lambda expression.
I have some λ-calculus background. Considering the following code, it
looks like Python is quite willing to perform side-effects in lambda
expressions:
#!/usr/bin/python
def applyTo42(f):
return f(42)
def double(x):
return x * 2
class ContainsVal:
def __init__(self, v):
self.v = v
def store(self, v):
self.v = v
def main():
print('== functional, no side effects')
print('-- print the double of 42')
print(applyTo42(double))
print('-- print 1000 more than 42')
print(applyTo42(lambda x: x + 1000))
print('-- print c\'s value instead of 42')
c = ContainsVal(23)
print(applyTo42(lambda x: c.v))
print('== not functional, side effects')
print('-- perform IO on 42')
applyTo42(lambda x: print(x))
print('-- set c\'s value to 42')
print(c.v)
applyTo42(lambda x: c.store(x))
print(c.v)
#print('== illegal, but why?')
#print(applyTo42(lambda x: c.v = 99))
if __name__ == '__main__':
main()
But if I uncomment the lines
print('== illegal, but why?')
print(applyTo42(lambda x: c.v = 99))
I'll get
SyntaxError: lambda cannot contain assignment
Why not? What is the deeper reason behind this?
As the code demonstrates, it cannot be about “purity” in a
functional sense.
The only explanation I can imagine is that assignemts do not
return anything, not even None. But that sounds lame and would
be easy to fix (one way: make lambda expressions return None if
body is a statement).
Not an answer:
Because it's defined that way (I want to know why it's defined that way).
Because it's in the grammar (see above).
Use def if you need statements (I did not ask for how to get
statements into a function).
“This would change syntax / the language / semantics” would be ok as an answer if you can come up with an example of such a change, and why it would be bad.
The entire reason lambda exists is that it's an expression.1 If you want something that's like lambda but is a statement, that's just def.
Python expressions cannot contain statements. This is, in fact, fundamental to the language, and Python gets a lot of mileage out of that decision. It's the reason indentation for flow control works instead of being clunky as in many other attempts (like CoffeeScript). It's the reason you can read off the state changes by skimming the first object in each line. It's even part of the reason the language is easy to parse, both for the compiler and for human readers.2
Changing Python to have some way to "escape" the statement-expression divide, except maybe in a very careful and limited way, would turn it into a completely different language, and one that no longer had many of the benefits that cause people to choose Python in the first place.
Changing Python to make most statements expressions (like, say, Ruby) would again turn it into a completely different language without Python's current benefits.
And if Python did make either of those changes, then there'd no longer be a reason for lambda in the first place;2,3 you could just use def statements inside an expression.
What about changing Python to instead make assignments expressions? Well, it should be obvious that would break "you can read off the state changes by skimming the first object in each line". Although Guido usually focuses on the fact that if spam=eggs is an error more often than a useful thing.
The fact that Python does give you ways to get around that when needed, like setattr or even explicitly calling __setitem__ on globals(), doesn't mean it's something that should have direct syntactic support. Something that's very rarely needed doesn't deserve syntactic sugar—and even more so for something that's unusual enough that it should raise eyebrows and/or red flags when it actually is done.
1. I have no idea whether that was Guido's understanding when he originally added lambda back in Python 1.0. But it's definitely the reason lambda wasn't removed in Python 3.0.
2. In fact, Guido has, multiple times, suggested that allowing an LL(1) parser that humans can run in their heads is sufficient reason for the language being statement-based, to the point that other benefits don't even need to be discussed. I wrote about this a few years ago if anyone's interested.
3. If you're wondering why so many languages do have a lambda expression despite already having def: In many languages, ranging from C++ to Ruby, function aren't first-class objects that can be passed around, so they had to invent a second thing that is first-class but works like a function. In others, from Smalltalk to Java, functions don't even exist, only methods, so again, they had to invent a second thing that's not a method but works like one. Python has neither of those problems.
4. A few languages, like C# and JavaScript, actually had perfectly working inline function definitions, but added some kind of lambda syntax as pure syntactic sugar, to make it more concise and less boilerplatey. That might actually be worth doing in Python (although every attempt at a good syntax so far has fallen flat), but it wouldn't be the current lambda syntax, which is nearly as verbose as def.
There is a syntax problem: an assignment is a statement, and the body of a lambda can only have expressions. Python's syntax is designed this way1. Check it out at https://docs.python.org/3/reference/grammar.html.
There is also a semantics problem: what does each statement return?
I don't think there is interest in changing this, as lambdas are meant for very simple and short code. Moreover, a statement would allow sequences of statements as well, and that's not desirable for lambdas.
It could be also fixed by selectively allowing certain statements in the lambda body, and specifying the semantics (e.g. an assignment returns None, or returns the assigned value; the latter makes more sense to me). But what's the benefit?
Lambdas and functions are interchangeable. If you really have a use-case for a particular statement in the body of a lambda, you can define a function that executes it, and your specific problem is solved.
Perhaps you can create a syntactic macro to allow that with MacroPy3 (I'm just guessing, as I'm a fan of the project, but still I haven't had the time to dive in it).
For example MacroPy would allow you to define a macro that transforms f[_ * _] into lambda a, b: a * b, so it should not be impossible to define the syntax for a lambda that calls a function you defined.
1 A good reason to not change it is that it would cripple the syntax, because a lambda can be in places where expressions can be. And statements should not. But that's a very subjective remark of my own.
My answer is based on chepner's comment above and doesn't draw from any other credible or official source, however I think that it will be useful.
If assignment was allowed in lambda expressions, then the error of confusing == (equality test) with = (assignment) would have more chances of escaping into the wild.
Example:
>>> # Correct use of equality test
... list(filter(lambda x: x==1, [0, 1, 0.0, 1.0, 0+0j, 1+0j]))
[1, 1.0, (1+0j)]
>>> # Suppose that assignment is used by mistake instead of equality testing
... # and the return value of an assignment expression is always None
... list(filter(lambda x: None, [0, 1, 0.0, 1.0, 0+0j, 1+0j]))
[]
>>> # Suppose that assignment is used by mistake instead of equality testing
... # and the return value of an assignment expression is the assigned value
... list(filter(lambda x: 1, [0, 1, 0.0, 1.0, 0+0j, 1+0j]))
[0, 1, 0.0, 1.0, 0j, (1+0j)]
As long as exec() (and eval()) is allowed inside lambda, you can do assignments inside lambda:
q = 3
def assign(var_str, val_str):
exec("global " + var_str + "; " +
var_str + " = " + val_str)
lambda_assign = lambda var_str, val_str: assign(var_str, val_str)
q ## gives: 3
lambda_assign("q", "100")
q ## gives: 100
## what would such expression be a win over the direct:
q = 100
## ? `lambda_assign("q", "100")` will be for sure slower than
## `q = 100` isn't it?
q_assign = lambda v: assign("q", v)
q_assign("33")
q ## 33
## but do I need lambda for q_assign?
def q_assign(v): assign("q", v)
## would do it, too, isn't it?
But since lambda expressions allow only 1 expression to be defined inside their body (at least in Python ...), what would be the point of to allow an assignment inside a lambda? Its net effect would be to assign directly (without using any lambda) q = 100, isn't it?
It would be even faster than doing it over a defined lambda, since you have at least one function lookup and execution less to execute ...
There's not really any deeper reasons, it has nothing to do with lambda or functional language designs, it's just to avoid programmers from mixing = and == operators, which is a very common mistake in other languages
IF there's more to this story, I assume like MAYBE because python bdfl GVR has expressed his unloving sides to lambda and other functional features and attempted(and conceded) to remove them from python 3 altogether https://www.artima.com/weblogs/viewpost.jsp?thread=98196
At the time of this writing the core devs were seen having a heated discussions recently on whether to include a limited name binding expression assignment, the debate is still on going so perhaps someday we may see it in lambda(unlikely)
As you said it yourself it is definitely not about side effects or purity, they just don't want lambda to be more than a single expression... ... ...
With that said, here's something about multi expressions assignments in lambda, read on if you're interested
It is not at all impossible in python, in fact it was sometimes necessary to capture variable and sidestep late bindings by (ab)using kwargs(keyword arguments)
edit:
code example
f = lambda x,a=1: (lambda c = a+2, b = a+1: (lambda e = x,d = c+1: print(a,b,c,d,e))())()
f("w")
# output 1 2 3 4 w
# expression assignment through an object's method call
if let(a=1) .a > 0 and let(b=let.a+1) .b != 1 and let(c=let.b+let.a) .c:
print(let.a, let.b, let.c)
# output 1 2 3
As it stands, Python was designed as a statement-based language. Therefore assignment and other name bindings are statements, and do not have any result.
The Python core developers are currently discussing PEP 572, which would introduce a name-binding expression.
I think all the fellows answered this already. We use mostly lambdas function when we just want to:
-create some simple functions that do the work perfectly in a specific place(most of the time hidden inside some other big functions
-The lambda function does not have a name
-Can be used with some other built-ins functions such as map, list and so forth ...
>>> Celsius = [39.2, 36.5, 37.3, 37.8]
>>> Fahrenheit = map(lambda x: (float(9)/5)*x + 32, Celsius) # mapping the list here
>>> print Fahrenheit
[102.56, 97.700000000000003, 99.140000000000001, 100.03999999999999]
Please visit this webpage , this could be useful.Keep it up !!!
https://www.python-course.eu/lambda.php

Python map function, passing by reference/value?

I have a question about the map function in Python.
From what I understand, the function does not mutate the list it's operating on, but rather create a new one and return it. Is this correct ?
Additionally, I have the following piece of code
def reflect(p,dir):
if(dir == 'X'):
func = lambda (a,b) : (a * -1, b)
else:
func = lambda (a,b) : (a, b * -1)
p = map(func,p)
print 'got', p
points is an array of tuples such as: [(1, 1), (-1, 1), (-1, -1), (1, -1)]
If I call the above function in such a manner:
print points
reflect(points,'X')
print points
the list points does not change. Inside the function though, the print function properly prints what I want.
Could someone maybe point me in some direction where I could learn how all this passing by value / reference etc works in python, and how I could fix the above ? Or maybe I'm trying too hard to emulate Haskell in python...
Thanks
edit:
Say instead of p = map(func,p) I do
for i in range(len(p)):
p[i] = func(p[i])
The value of the list is updated outside of the function, as if working by reference. Ugh, hope this is clear :S
You misunderstand how references work in Python. Here, all names are references, there are no "values". Names are bound to objects. But = doesn't modify the object that's pointed to by the name — it rebinds the name to a different object:
x = 42
y = x
# now:
# 'is' is a identity operator — it checks whether two names point to the
# exact same object
print x is y # => True
print x, y # 42 42
y = 69
# now y has been rebound, but that does not change the '42' object, nor rebinds x
print x is y # => False
print x, y # 42 69
To modify the object itself, it needs to be mutable — i.e. expose members that mutate it or have a modifiable dict. The same thing as above happens when you rebind p — it doesn't touch points at all, it simply modifies the meaning of local p name.
If you want to simulate C++-like references, you need to encapsulate the object into a mutable container, e.g. a list.
reflect([points], 'X')
# inside reflect:
p[0] = ...
But you shouldn't, at least in this case — you should just return the new object instead.
points = reflect(points, 'X')
# inside reflect, instead of p = ...
return map(func, p)
Well, now that I think about it, you can also do
p[:] = map(func, p)
But again, returning new object is usually better.
The data model of Python is based on a trilogy:
identifier - reference - object
.
The identifier is a string written in the code.
The reference is a variable stricto sensu, that is to say "a chunk of
memory whose content can change". The value of a reference is the adress of the object.
The object has an
implementation based on the structures of the langage C that is the
foundations of Python.
Other words are also used to designate the 'identifier' :
1) name
2) variable ; because this word is used by metonymy in mathematics to designate the symbols that represent the real mathematical variables, and the variables in a computer have conceptually the same functioning as the mathematical variables (their values can change).
This use in Python is a very bad habit in my opinion : it creates ambiguities and confusion with what is called 'variable' in computer science: "chunk of memory whose content can change".
The best is to use the word : identifier
.
An identifier and an object are binded in a certain namespace. Namespaces are displayed under the form of Python's dictionaries, but they ARE NOT dictionaries.
The binding of the identifier and the object is indirect, via the reference.
The binding of the identifier and the reference is direct, and realized in the SYMBOL TABLE (or symbol-table).
In computer science, a symbol table is a data structure used by a
language translator such as a compiler or interpreter, where each
identifier in a program's source code is associated with information
relating to its declaration or appearance in the source, such as its
type, scope level and sometimes its location.
http://en.wikipedia.org/wiki/Symbol_table
They say: identifiers. Precisely.
I rarely see allusions to symbol table, though it's the crucial thing that sheds light on the functioning of the Python's data model IMO.
In my opinion, the word
binding
doesn't designate a precise and unique mechanism but globally the set of all the mechanisms concerning the trilogy identifier - reference - object
.
I dont' pretend that I perfectly understood all the matters concerning the data and execution models of Python, and that the above considerations are the more exact and precisely expressed that can be done.
However, they allow me to have an operational understanding of what happens during executions of code.
I would be very happy to be corrected on some points if I am wrong (for exemple, I am very satisfied to have learnt from Michael Foord that the nature of namespaces is not being dictionary, which is only the way they are represented)
.
That said, I don't know what is called value and reference when the subject of passing something as argument in Python is discussed, and I have the impression that a lot of the persons that have expressed on the subject in numerous esoteric discussions don't know more than me.
I think that there is no best and lucid opinion on the subject that this one of Alex Martelli:
"Trying to reuse terminology that is more generally applied to
languages where "variables are boxes" to a language where "variables
are post-it tags" is, IMHO, more likely to confuse than to help."
Alex Martelli
http://bytes.com/topic/python/answers/37219-value-reference
I want to bump this. The answers don't really answer the question - they disregard the fact that the OP was able to achieve the desired result by iterating. The question comes down to the behavior of map. Here is a more direct example:
f=(lambda pair: pair[0].append(pair[1]))
a = ([],1)
f(a)
print(a) #prints ([1],1)
a=([],1)
map(f,[a])
print(a) #prints ([0],1)
So map isn't mutating objects in the way the OP is expecting. I have the same confusion.
Can anyone comment on exactly what is going on here? I think that'd be a good answer to the OP's question.
Note that we have different behavior if we assign the output of map as follows (as per Cat Plus Plus' answer)
f=(lambda pair: pair[0].append(pair[1]))
a = ([],1)
x = [a]
x[:] = map(f,x)
print(x) #prints None
print(a) # prints [1]
Please note that in the first example, we simply called f(a), not a=f(a). Why do we need assignment when using map and not when working outside of map?

Is there a way to convert code to a string and vice versa in Python?

The original question was:
Is there a way to declare macros in Python as they are declared in C:
#define OBJWITHSIZE(_x) (sizeof _x)/(sizeof _x[0])
Here's what I'm trying to find out:
Is there a way to avoid code duplication in Python?
In one part of a program I'm writing, I have a function:
def replaceProgramFilesPath(filenameBr):
def getProgramFilesPath():
import os
return os.environ.get("PROGRAMFILES") + chr(92)
return filenameBr.replace("<ProgramFilesPath>",getProgramFilesPath() )
In another part, I've got this code embedded in a string that will later be
output to a python file that will itself be run:
"""
def replaceProgramFilesPath(filenameBr):
def getProgramFilesPath():
import os
return os.environ.get("PROGRAMFILES") + chr(92)
return filenameBr.replace("<ProgramFilesPath>",getProgramFilesPath() )
"""
How can I build a "macro" that will avoid this duplication?
Answering the new question.
In your first python file (called, for example, first.py):
import os
def replaceProgramFilesPath(filenameBr):
new_path = os.environ.get("PROGRAMFILES") + chr(92)
return filenameBr.replace("<ProgramFilesPath>", new_path)
In the second python file (called, for example, second.py):
from first import replaceProgramFilesPath
# now replaceProgramFilesPath can be used in this script.
Note that first.py will need to be in python's search path for modules or the same directory as second.py for you to be able to do the import in second.py.
No, Python does not support preprocessor macros like C. Your example isn't something you would need to do in Python though; you might consider providing a relevant example so people can suggest a Pythonic way to express what you need.
While there does seem to be a library for python preprocessing called pypp, I am not entirely familiar with it. There really is no preprocessing capability for python built-in. Python code is translated into byte-code, there are no intermediate steps. If you are a beginner in python I would recommend avoiding pypp entirely.
The closest equivalent of macros might be to define a global function. The python equivalent to your C style macro might be:
import sys
OBJWITHSIZE = lambda x: sys.getsizeof(x) / sys.getsizeof(x[0])
aList = [1, 2, 4, 5]
size = OBJWITHSIZE(aList)
print str(size)
Note that you would rarely ever need to get the size of a python object as all allocation and deletion are handled for you in python unless you are doing something quite strange.
Instead of using a lambda function you could also do this:
import sys
def getSize(x):
return sys.getsizeof(x) / sys.getsizeof(x[0])
OBJWITHSIZE = getSize
aList = [1, 2, 4, 5]
size = OBJWITHSIZE(aList)
print str(size)
Which is essentially the same.
As it has been previously mentioned, your example macro is redundant in python because you could simply write:
aList = [1, 2, 4, 5]
size = len(aList)
print str(size)
This is not supported at the language level. In Python, you'd usually use a normal function or a normal variable where you might use a #define in C.
Generally speaking if you want to convert string to python code, use eval. You rarely need eval in Python. There's a module somewhere in the standard library that can tell you a bit about an objects code (doesn't work in the interp), I've never used it directly. You can find stuff on comp.lang.python that explains it.
As to 'C' macros which seem to be the real focus of your question.
clears throat DO NOT USE C MACROS IN PYTHON CODE.
If all you want is a C macro, use the C pre processor to pre process your scripts. Duh.
If you want #include, it's called import.
If you want #define, use an immutable object. Think const int foo=1; instead of #define foo 1. Some objects are immutable, like tuples. You can write a function that makes a variable sufficiently immutable. Search the web for an example. I rather like static classes for some cases like that.
If you want FOO(x, y) ... code ...; learn how to use functions and classes.
Most uses of a 'CPP' macro in Python, can be accomplished by writing a function. You may wish to get a book on higher order functions, in order to handle more complex cases. I personally like a book called Higher Order Perl (HOP), and although it is not Python based, most of the book covers language independent ideas -- and those ideas should be required learning for every programmer.
For all intents and purposes the only use of the C Pre Processor that you need in Python, that isn't quite provided out of box, is the ability to #define constants, which is often the wrong thing to do, even in C and C++.
Now implementing lisp macros in python, in a smart way and actually needing them... clears throat and sweeps under rug.
Well, for the brave, there's Metapython:
http://code.google.com/p/metapython/wiki/Tutorial
For instance, the following MetaPython code:
$for i in range(3):
print $i
will expand to the following Python code:
print 0
print 1
print 2
But if you have just started with Python, you probably won't need it. Just keep practicing the usual dynamic features (duck typing, callable objects, decorators, generators...) and you won't feel any need for C-style macros.
You can write this into the second file instead of replicating the code string
"""
from firstFile import replaceProgramFilesPath
"""

Python: Using vars() to assign a string to a variable

I find it very useful to be able to create new variables during runtime and create a dictionary of the results for processing later, i.e. writing to a file:
myDict = {}
for i in range (1,10):
temp = "variable"+str(i)
vars()[temp] = myFunctionThatReturnsData() # variable1= data1, variable2 = data2,etc.
myDict[temp] = vars(temp)
which creates the dictionary entry [result1:data1] which i can call with myDict[result1]. I have been using vars() without really understanding what I'm doing. I take it vars() returns a dictionary with the local variables(?), and
vars()[x] = y
creates a new dictionary entry of [x:y] ?
I have a script where I pass in a dictionary prepared with {input1:data1,input2:data2}, and i use this method to iterate through all the values, store all the results, and output it to a file. This bit of code is inside a function within a class, and is working.
My source of confusion is that I have read various posts on how locals() shouldn't be messed with, and how vars() is equivalent(?) to locals(), or globals()..
So my question is (at least) two-fold:
1.What exactly does vars(),or in particular, vars()[x] = y do,
2.What the scope of this dictionary is (what I need to keep in mind as I write bigger programs
3.Whether this is good programming practice.
Thanks in advance!
The pythonic way to create a sequence of variables
If you want a sequence of variables, create a sequence. Instead of trying to create independent variables like:
variable0
variable1
variable2
variable3
You should look at creating a list. This is similar to what S.Lott is suggesting (S.Lott usually has good advice), but maps more neatly onto your for loop:
sequence = []
for _ in xrange(10):
sequence.append(function_that_returns_data())
(Notice that we discard the loop variable (_). We're just trying to get 10 passes.)
Then your data will be available as:
sequence[0]
sequence[1]
sequence[2]
sequence[3]
[...]
sequence[9]
As an added bonus, you can do:
for datum in sequence:
process_data(datum)
At first, you may twitch at having your sequence start at 0. You can go through various contortions to have your actual data start at 1, but it's more pain than it's worth. I recommend just getting used to having zero-based lists. Everything is built around them, and they start to feel natural pretty quickly.
vars() and locals()
Now, to answer another part of your question. vars() (or locals()) provides low level access to variables created by python. Thus the following two lines are equivalent.
locals()['x'] = 4
x = 4
The scope of vars()['x'] is exactly the same as the scope of x. One problem with locals() (or vars()) is that it will let you put stuff in the namespace that you can't get out of the namespace by normal means. So you can do something like this: locals()[4] = 'An integer', but you can't get that back out without using locals again, because the local namespace (as with all python namespaces) is only meant to hold strings.
>>> x = 5
>>> dir()
['__builtins__', '__doc__', '__name__', 'x']
>>> locals()[4] = 'An integer'
>>> dir()
[4, '__builtins__', '__doc__', '__name__', 'x']
>>> x
5
>>> 4
4
>>> locals()[4]
'An integer'
Note that 4 does not return the same thing as locals()[4]. This can lead to some unexpected, difficult to debug problems. This is one reason to avoid using locals(). Another is that it's generally a lot of complication just to do things that python provides simpler, less error prone ways of doing (like creating a sequence of variables).
Do this instead. It's simpler.
myDict = {}
for i in range (1,10):
temp = "variable"+str(i)
myDict[temp] = myFunctionThatReturnsData() # variable1= data1, variable2 = data2,etc.
That's all you ever need to do.
The results will be myDict['variable1'] through myDict['variable9']
You rarely need vars() or locals(). Just stop using them and use ordinary variables and ordinary dictionaries. Try to avoid things you don't understand and stick to the simple, obvious stuff.
From the help for vars,
vars(...)
vars([object]) -> dictionary
Without arguments, equivalent to locals().
With an argument, equivalent to object.__dict__.
You are using it without vars, so let's look at the help for locals()
locals(...)
locals() -> dictionary
Update and return a dictionary containing the current scope's local
variables.
So this answers you first two questions. vars() returns a dictionary to the local variables that is indexed by the name of the variable as a string. The scope is local.
I'm not sure about the third question, but it does seem like kind of a hack which isn't a good sign. I guess if you're careful about using this only in the correct scope you can get by with it.
jcdyer explains the concepts very well and Justin Peel clearly states what vars() and locals() do. But a small example always speeds up understanding.
class Bull(object):
def __init__(self):
self.x = 1
self.y = "this"
def __repr__(self):
return "Bull()"
def test1(self):
z = 5
return vars()
def test2(self):
y = "that"
return vars(self)
def test3(self):
return locals()
def test4(self):
y = 1
return locals()
if __name__ == "__main__":
b = Bull()
print b.test1()
print b.test2()
print b.test3()
print b.test4()
print vars(b).get("y")
Which results in:
{'self': Bull(), 'z': 5}
{'y': 'this', 'x': 1}
{'self': Bull()}
{'y': 1, 'self': Bull()}
this
I can answer number 3: this isn't good programming practice. I don't exactly see what you are trying to accomplish, but I am sure there is a more elegant way of doing it without using locals() (which is the same as vars() according to help(vars) in the interactive Python shell).
Using vars / locals or globals in this way is (a) poor practice and (b) doesn't work in all cases. See Dynamically set local variable for more details. Bottom line: just use dicts -- that's what they're for.
I also search for this answer at many places. The best one I see so far is:
var_list = ["Var_Name{}".format(i) for i in range(1,100)]

Categories

Resources