What is "lambda binding" in Python? [duplicate] - python

This question already has answers here:
What do lambda function closures capture?
(7 answers)
Closed 6 months ago.
I understand what are lambda functions in Python, but I can't find what is the meaning of "lambda binding" by searching the Python docs.
A link to read about it would be great.
A trivial explained example would be even better.
Thank you.

First, a general definition:
When a program or function statement
is executed, the current values of
formal parameters are saved (on the
stack) and within the scope of the
statement, they are bound to the
values of the actual arguments made in
the call. When the statement is
exited, the original values of those
formal arguments are restored. This
protocol is fully recursive. If within
the body of a statement, something is
done that causes the formal parameters
to be bound again, to new values, the
lambda-binding scheme guarantees that
this will all happen in an orderly
manner.
Now, there is an excellent python example in a discussion here:
"...there is only one binding for x: doing x = 7 just changes the value in the pre-existing binding. That's why
def foo(x):
a = lambda: x
x = 7
b = lambda: x
return a,b
returns two functions that both return 7; if there was a new binding after the x = 7, the functions would return different values [assuming you don't call foo(7), of course. Also assuming nested_scopes]...."

I've never heard that term, but one explanation could be the "default parameter" hack used to assign a value directly to a lambda's parameter. Using Swati's example:
def foo(x):
a = lambda x=x: x
x = 7
b = lambda: x
return a,b
aa, bb = foo(4)
aa() # Prints 4
bb() # Prints 7

Where have you seen the phrase used?
"Binding" in Python generally refers to the process by which a variable name ends up pointing to a specific object, whether by assignment or parameter passing or some other means, e.g.:
a = dict(foo="bar", zip="zap", zig="zag") # binds a to a newly-created dict object
b = a # binds b to that same dictionary
def crunch(param):
print param
crunch(a) # binds the parameter "param" in the function crunch to that same dict again
So I would guess that "lambda binding" refers to the process of binding a lambda function to a variable name, or maybe binding its named parameters to specific objects? There's a pretty good explanation of binding in the Language Reference, at http://docs.python.org/ref/naming.html

Related

Does Python scoping rule fits the definition of lexical scoping? [duplicate]

This question already has answers here:
What do lambda function closures capture?
(7 answers)
Closed 6 months ago.
According to my programming language class, in a language that uses lexical scoping
The body of a function is evaluated in the environment where the
function is defined, not the environment where the function is called.
For example, SML follows this behavior:
val x = 1
fun myfun () =
x
val x = 10
val res = myfun() (* res is 1 since x = 1 when myfun is defined *)
On the other hand, Python does not follow this behavior:
x = 1
def myfun():
return x
x = 10
myfun() # 10 since x = 10 when myfun is called
So why is Python described as using lexical scoping?
Your Python myfun is using the x variable from the environment where it was defined, but that x variable now holds a new value. Lexical scoping means functions remember variables from where they were defined, but it doesn't mean they have to take a snapshot of the values of those variables at the time of function definition.
Your Standard ML code has two x variables. myfun is using the first variable.
In Python, just as in SML, or (modern) Lisp, the body of a function is evaluated in the environment where it was defined. So, all three languages are lexically scoped.
In Python and Lisp, environments are mutable. That is, you can assign a new value to an existing variable, and that mutates the environment the variable is part of. Any functions defined within that environment will be evaluated in that environment—which means they will see the new value of the variable.
In SML, environments are not mutable; the environment can't change, there is no new value, so there's no question of whether the function will see that new value.
The syntax can be a bit misleading. In ML, val x = 1 and val x = 10 both define a brand new variable. In Python, x = 1 and x = 10 are assignment statements—they reassign to an existing variable, only defining a new one if there wasn't one of that name yet. (You don't see this in Lisp, where, e.g., let and setq are pretty hard to confuse.)
By the way, a closure with mutable variables is functionally equivalent to a mutable object (in the OO sense), so this feature of Lisp (and Python) has traditionally been pretty important.
As a side note, Python actually has slightly special rules for the global namespace (and the builtins one above it), so you could argue that the code in your example technically isn't relying on lexical scoping. But if you put the whole thing inside a function and call that function, then it definitely is an example of lexical scoping, so the global issue really isn't that important here.
In addition to the responses of #abarnert and #user2357112, it may help you to consider an SML equivalent of the Python code:
val x = ref 1
fun myfun () = !x
val () = x := 10
val res = myfun ()
The first line declares a variable x that references an integer and sets the referenced cell to 1. The function body dereferences x to return the value in the referenced cell. The third line sets the referenced cell to 10. The function call in the fourth line now returns 10.
I used the awkward val () = _ syntax to fix an ordering. The declaration is added solely for its side effect on x. It is also possible to write:
val x = ref 1
fun myfun () = !x;
x := 10;
val res = myfun ()
The environment is immutable—notably x always points to the same memory cell—but some data structures (reference cells and arrays) are mutable.
Let me start with a rationale that helped me understand the matter (and write this answer).
There are two concepts that overlap each other in the evaluation of variables in Python that may create some confusion:
One is the (memory) lookup strategy Python deploys to evaluate a variable, the famous BGEL order (Built-in < Global < Enclosing < Local scopes).
The other is the scope in which an object (function, variable) is defined and/or evaluated.
As the OP notes, Python doesn't look lexically scoped when we can switch the value of our variable ("x"), or from the fact that we can define a function (using "x") without even declaring the variables therein a priori; E.g.,
> def f():
print(x)
> x = 1
> f()
1
What is lexical scope
So, what is lexical scope after all, and how does it work in Python?
Lexical scope means that an object's (memory) scope will that where it (i.e., the object) was defined.
Let's take a function "f()", for instance. A function has an inner scope and an outer scope. In a lexically scoped language (eg, Python), the outer scope of "f()" will be the scope where the function was defined. Always. Even if you evaluate your function (f()) anywhere else in your code, the outer scope of f() will always be that where it was defined.
So, when Python applies its BGEL symbols evaluation strategy, the "E" is where lexical scope comes into action: the scope where f() was defined.
Lexical scope at work
> def f():
print(x)
> def g(foo):
x = 99
foo()
print(x)
> x = 1
> g(f)
1
99
We then can see the recursive (BGEL) scope search strategy on evaluating variables is respecting the scopes local-and-above where the function 'f()' was defined.

What is masking here [duplicate]

This question already has answers here:
masking the built-in variable with its magic behavior?
(2 answers)
Closed 6 years ago.
In the python tutorial:
In interactive mode, the last printed expression is assigned to the variable _. This means that when you are using Python as a desk calculator, it is somewhat easier to continue calculations, for example:
>>> tax = 12.5 / 100
>>> price = 100.50
>>> price * tax
12.5625
>>> price + _
113.0625
>>> round(_, 2)
113.06
This variable should be treated as read-only by the user. Don’t explicitly assign a value to it — you would create an independent local variable with the same name masking the built-in variable with its magic behavior.
What is masking here?
In general what is meant by masking or mask variable in python?
THanks
A variable is masked if some other variable with the same name exists, which is preferred. An example is having a global variable x. If you're in a function which also has a local variable x, then the global won't be accessible, without special measures the local variable is preferred whenever you use identifier x inside the function.
It's as if you have two kids in your classroom both called Mary, one of which is closer, and will hear your voice earlier, so always gives the quickest answer. How to give the other girl a chance?
Overwriting/reassigning a previously named identifier in a new scope
let's look at this code for example
def f():
return 3
def g():
f = 5
f()
try:
print(g())
except TypeError:
print(f())
within the scope of g, the identifier f has been reassigned from a function that returns an integer, to just an integer. so when you try calling f inside of g you should get a type error because you can't call an int. however outside of g, f is still a function that returns 3
the interpreter has its own scope so when you assign _ to another value, it forgets it's previous functionality in replace of the new value, until you restart the interpreter, or in this special case delete it with the del keyword
The _ is built-in to the interpreter, it has special meaning. It only acts like a read-only variable. When you read from it, the interpreter replaces it with the last calculated value. If you do something like
_ = 1 + 1
You are actually creating a new variable named _ in the current namespace (try running locals()function before and after creating the variable). Since there is now a variable with the same name as the interpreter built-in _ that variable is accessed first when you do subsequent reads, thus hiding the meaning of the built-in, or masking it.
You can also do what you're doing with Python built-ins as well, such as defining a function parameter namedint. In the the local function namespace, if you tried to call theint() function on a value, it would attempt to use your parameterint as a callable because there is a local variable with that name masking the built-in function int. Some IDEs will warn you when you try to do something like this because in practice it is generally a bad idea to mask the name of a built-in like that because you're eliminating the behavior of that what that symbol is intended for.
Where making comes in its if you do something like
val = 20
def do_stuff(val):
# parameter masks the value defined in outer scope
print('Value of a inside function: {}'.f format(val))
do_stuff(10) # prints 10
This assigns a variable val a value of 20, but when the function do_stuff is called it had it's own local variable namedval. Accessingval from within the function will give you the value passed in, 10 in this case, not 20 from the outer variable because thea within the function masks the one in the outer scope.

Callback function tkinter button with variable parameter [duplicate]

This question already has answers here:
tkinter creating buttons in for loop passing command arguments
(3 answers)
Closed 10 months ago.
from tkinter import *
F=Tk()
i=1
while i<10:
newButton = Button(F,text="Show Number",command=lambda:showNumber(i))
newButton.pack(side=TOP)
i+=1
def showNumber(nb):
print(nb)
F.mainloop()
All buttons return 10. Why ?
I want button 1 return 1, button 2 return 2...
Thank you very much for helping me
Your anonymous lambda functions are can be though of as closures (as #abernert points out, they're not actually closures in Python's case) - they "close over" the variable i, to reference it later. However, they don't look up the value at the time of definition, but rather at the time of calling, which is some time after the entire while loop is over (at which point, i is equal to 10).
To fix this, you need to re-bind the value of i to a something else for the lambda to use. You can do this in many ways - here's one:
...
i = 1
while i < 10:
# Give a parameter to the lambda, defaulting to i (function default
# arguments are bound at time of declaration)
newButton = Button(F, text="Show Number",
command=lambda num=i: showNumber(num))
...
This is explained in the Python FAQ: Why do lambdas defined in a loop with different values all return the same result?.
Quoting the FAQ answer:
This happens because x is not local to the lambdas, but is defined in the outer scope, and it is accessed when the lambda is called — not when it is defined…
In order to avoid this, you need to save the values in variables local to the lambdas, so that they don’t rely on the value of the global…
In other words, your new functions aren't storing the value of i, they're storing the variable i. And they're all storing the same variable i, which has the value 10 at the end of your loop. In fact, if you add an i = 'spam' right before F.mainloop(), you'll see that all the buttons now print out the string spam instead of a number.
This is very useful when you're trying to create closures—functions that can affect their defining environment.* But when you're not trying to do so, that can get in the way.
The simplest way around this is to use a parameter with a default value. Default values don't hold variables; just values, which are evaluated at the time the function is defined. So:
newButton = Button(F,text="Show Number", command=lambda num=i: showNumber(num))
* Note that in this case, there aren't actually any closures involved, because i is a global, rather than a local in the enclosing scope. But really, this is just because Python has special handling for globals and doesn't need a closure here; conceptually, if you think of there being one, you won't get into any trouble unless you start looking at the __closure__ or __code__ attributes.

Why doesn't python allow passing variables by reference [duplicate]

This question already has answers here:
How do I pass a variable by reference?
(39 answers)
Closed 6 months ago.
This probably fits more a discussion group, but I'm not proficient in the
innards of the language (or even the language itself). In any case, what's bugging me is:
If python is allowing interference (side effects) with outer scope using the nonlocal keyword, then why does it not allow a similar interference with function arguments by
permitting passing arguments by reference:
Possible right now:
>>> def outer():
x = 1
def inner():
nonlocal x
x = 2
print("inner:", x)
inner()
print("outer:", x)
>>> outer()
inner: 2
outer: 2
Why not - or what could go wrong if we had:
>>> def outer():
x = 1
def inner(byref x):
x = 2
print("inner:", x)
inner(x)
print("outer:", x)
>>> outer()
inner: 2
outer: 2
(using some keyword like 'byref' or 'nonlocal, just for illustration).
Python always passes parameters using reference value. Refer to this link here and especially rad the detailed response provided by the user pepr
Also this link has pretty detailed discussion on how exactly parameters are passed within python and also pass-by-reference can be simulated - refer to the EDIT of the accepted answer to this question.
In case, you want to delve deeper - please refer to this Effbot article that also contains some debate/discussions around the same topic.
This is not possible because Python does not have a concept of "variable" at all. All the names in a Python program are references to objects. So you can only pass a reference to an object when calling a function or method. This is called passing by reference value.
However, it is not possible to obtain a reference to an existing reference. In this respect, references are the only "non first class" citizens in the Python world.
There are two kinds of objects referenced by names in a program: immutable (e.g. string, int, tuple) an mutable (e.g. list, set, most user classes).
You can call methods on mutable objects that in fact modify the objects state, and this looks similar to passing a reference to the object in a language such as C++. Beyond that, the passing by reference does not make much sense in Python.
See Prahalad Deshpande's answer for some links.
Suppose you do allow reference arguments. What happens, then, when you do the following?
def f(byref x):
print x
print x
x = 3
class Foo(object):
def __init__(self):
self.count = 0
#property
def x(self):
count += 1
return count
f(Foo().x)
When is the getter called? How many times is it called? Does this print 1 twice, or does it print 1, then 2, or 2, then 3? Since there's no setter, what happens when you try to assign to x?
In another language, where variables are places to put things instead of names for values, this wouldn't be a problem. Foo().x would have a memory location once evaluated, and f would use that memory location for its x argument. In Python, it doesn't work like that. You can't pass in the memory location of 1 and change its contents, because then other code will find that 1 is magically 2 all of a sudden. Python's name semantics and attribute/item getter/setters make reference arguments even more confusing than in languages like C++, where they're already confusing and bug-prone.
In Python int objects are immutable. When you think you are changing the value of x, you are really creating a new int at a different memory location and getting x to reference that.

Python Lambdas and Variable Bindings [duplicate]

This question already has answers here:
What do lambda function closures capture?
(7 answers)
Creating functions (or lambdas) in a loop (or comprehension)
(6 answers)
Closed 6 months ago.
I've been working on a basic testing framework for an automated build. The piece of code below represents a simple test of communication between two machines using different programs. Before I actually do any tests, I want to completely define them - so this test below is not actually run until after all the tests have been declared. This piece of code is simply a declaration of a test.
remoteTests = []
for client in clients:
t = Test(
name = 'Test ' + str(host) + ' => ' + str(client),
cmds = [
host.start(CMD1),
client.start(CMD2),
host.wait(5),
host.stop(CMD1),
client.stop(CMD2),
],
passIf = lambda : client.returncode(CMD2) == 0
)
remoteTests.append(t)
Anyhow, after the test is run, it runs the function defined by 'passIf'. Since I want to run this test for multiple clients, I'm iterating them and defining a test for each - no big deal. However, after running the test on the first client, the 'passIf' evaluates on the last one in the clients list, not the 'client' at the time of the lambda declaration.
My question, then: when does python bind variable references in lambdas? I figured if using a variable from outside the lambda was not legal, the interpretor would have no idea what I was talking about. Instead, it silently bound to the instance of the last 'client'.
Also, is there a way to force the resolution the way I intended it?
The client variable is defined in the outer scope, so by the time the lambda is run it will always be set to the last client in the list.
To get the intended result, you can give the lambda an argument with a default value:
passIf = lambda client=client: client.returncode(CMD2) == 0
Since the default value is evaluated at the time the lambda is defined, its value will remain correct.
Another way is to create the lambda inside a function:
def createLambda(client):
return lambda: client.returncode(CMD2) == 0
#...
passIf = createLambda(client)
Here the lambda refers to the client variable in the createLambda function, which has the correct value.
What happens is that your passIf argument, the lambda, refers to the variable client from the enclosing scope. It doesn't refer to the object the variable client refers to when it is created, but the variable itself. If you call these passIf after the loop has ended, that means they all refer to the last value in the loop. (In closure terminology, Python's closures are late-binding, not early-binding.)
Fortunately it's fairly easy to make a late-binding closure into an early-binding closure. You can do it by simply giving the lambda an argument with as default the value you want to bind:
passIf = lambda client=client: client.returncode(CMD2) == 0
That does mean the function gets that extra argument, and might mess things up if it gets called with an argument by accident -- or when you want the function to take arbitrary arguments. So another technique is to do it like this:
# Before your loop:
def make_passIf(client):
return lambda: client.returncode(CMD2) == 0
# In the loop
t = Test(
...
passIf = make_passIf(client)
)

Categories