Declaring variables inside a function python - python-3.x

For some reason I keep getting error in my code stating that my variables have not been declared. This only happens when I try to declare them in a function and not outside.
example
x, y = 105,107
print (x,y)
the above line of code works and gives me the output 105 107
but when I do this below
def fun1():
x, y = 105,107
print (x,y)
I get NameError: name 'x' is not defined
need help to understand what's happening.

One of the main utilities of functions is exactly the way they allow one
to isolate variables - no worries about clashing names for the code
in various functions - once a function works properly, it is done.
But if one needs to expose variables that populated inside functions to
the outside world, it is possible with the keyword "global". Notice that this
is in general considered bad practice, and even for small scripts,
there are often better solutions. But, common sense should always be the rule:
def fun1():
global x, y
x, y = 105, 107
fun1()
print(x, y)
Note that your code had another incorrect assumption: code
inside function bodies is not executed unless the function is called -
so, in the example in your question, even if you had declared
the variables as global, the print call would still
raise the same error, since you are not executing the line
that defines these variables by calling the function.
Now, you've learned about "globals" - next step is forget it
exists and learn how to work with variables properly encapsulated
inside functions, and when you get to some intermediate/advanced
level, then you will be able to judge when "globals" might actually
do more good than harm (which is almost never).

Related

PyQT QPushButton Connection Problem - Wrong function being called [duplicate]

Im trying to build a calculator with PyQt4 and connecting the 'clicked()' signals from the buttons doesn't work as expected.
Im creating my buttons for the numbers inside a for loop where i try to connect them afterwards.
def __init__(self):
for i in range(0,10):
self._numberButtons += [QPushButton(str(i), self)]
self.connect(self._numberButtons[i], SIGNAL('clicked()'), lambda : self._number(i))
def _number(self, x):
print(x)
When I click on the buttons all of them print out '9'.
Why is that so and how can i fix this?
This is just, how scoping, name lookup and closures are defined in Python.
Python only introduces new bindings in namespace through assignment and through parameter lists of functions. i is therefore not actually defined in the namespace of the lambda, but in the namespace of __init__(). The name lookup for i in the lambda consequently ends up in the namespace of __init__(), where i is eventually bound to 9. This is called "closure".
You can work around these admittedly not really intuitive (but well-defined) semantics by passing i as a keyword argument with default value. As said, names in parameter lists introduce new bindings in the local namespace, so i inside the lambda then becomes independent from i in .__init__():
self._numberButtons[i].clicked.connect(lambda checked, i=i: self._number(i))
UPDATE: clicked has a default checked argument that would override the value of i, so it must be added to the argument list before the keyword value.
A more readable, less magic alternative is functools.partial:
self._numberButtons[i].clicked.connect(partial(self._number, i))
I'm using new-style signal and slot syntax here simply for convenience, old style syntax works just the same.
You are creating closures. Closures really capture a variable, not the value of a variable. At the end of __init__, i is the last element of range(0, 10), i.e. 9. All the lambdas you created in this scope refer to this i and only when they are invoked, they get the value of i at the time they are at invoked (however, seperate invocations of __init__ create lambdas referring to seperate variables!).
There are two popular ways to avoid this:
Using a default parameter: lambda i=i: self._number(i). This work because default parameters bind a value at function definition time.
Defining a helper function helper = lambda i: (lambda: self._number(i)) and use helper(i) in the loop. This works because the "outer" i is evaluated at the time i is bound, and - as mentioned before - the next closure created in the next invokation of helper will refer to a different variable.
Use the Qt way, use QSignalMapper instead.

Scope of Functions as objects in Python

I am trying to understand how python stores and accesses its functions as objects .
For example take the following code-
def make_pretty(func):
def inner():
print("I got decorated")
func()
return func
return inner
def ordinary():
print("I am ordinary 2")
ordinary()
pretty=make_pretty(ordinary)
pretty()
When executed , pretty() returns
I got decorated
I am ordinary 2
<function __main__.ordinary()>
which seems to imply that the ordinary() function passed to make_pretty() is accessed as in the main scope, and as dir(pretty) doesn't show ordinary (Please correct me if i am wrong).
Now if I run this code after this
def ordinary():
print("I am ordinary 3")
pretty()
I still get the same output as before , even though I have the changed the global definition of ordinary , i.e. pretty still is considering the previous definition of ordinary even though I have redefined ordinary and the func in pretty is referring to global ordinary
Why is this so? I clearly am wrong somewhere but I don't understand where.
Some insight would be appreciated. Thanks
even though I have the changed the global definition of ordinary ,
i.e. pretty still is considering the previous definition of ordinary
even though I have redefined ordinary and the func in pretty is
referring to global ordinary
You didn't change the function object that pretty refers to. You created a new function, and gave the name ordinary to it. The original function still exists, but can no longer be referred to by the name ordinary.
pretty doesn't know about all this. It refers to the original function all the time.
Before
Both the name "ordinary" and the function pretty refer to the same function:
<function 1> <-- "ordinary"
<-- pretty
After
The name "ordinary" refers to a new function, but pretty still refers to the original function:
<function 1> <-- pretty
"ordinary" --> <function 2>

Call nested Python 3 nested function from parent function

For Python 3. I want to call a nested function from a top-level function. NOT access a variable in a nested function but call a nested function (what I'd normally refer to as a subroutine) from a "parent" function.
Answers on SO and elsewhere describe how to use the global and nonlocal keywords to enable variables in nested functions to be accessed by "parent" functions. But I haven't been able to translate that technique to Python 3 nested functions.
What I'm hoping to achieve, largely for outer-to-inner readability, is:
def topLevelFunction(listOfStrings):
# Top-level function's code here.
desiredValue = nestedFunction(dataToModify)
return(desiredResult)
# This nested function's source code is visibly contained within its parent.
def nestedFunction(oneListEntry):
# Modify data passed to function.
return(fixedData)
This structure of course produces UnboundLocalError: local variable 'nestedFunction' referenced before assignment.
I've circumvented that with:
def topLevelFunction(listofStrings):
def nestedFunction(oneListEntry):
# nestedFunction's code goes here.
return(fixedData)
# topLevelFunction's code goes here.
# Only in this "upside down" structure can top-level function call nestedFunction?
return(desiredResult)
Part of the problem seems to be that the nonlocal / global keywords that enable me to reference variables outside of nested functions' scope haven't enabled me to do the same thing for nested functions themselves(?) Or if they do, the syntax is unique? If that's the case, thanks for a pointer to that specific syntax.
I've also made nestedFunction a stand-alone function at the same level / scope as topLevelFunction. But at least from a readability perspective both circumventions (I won't call them fixes) seem to require me to write "upside down" code where things that are used later in the program flow must be "higher" in the source code?
Perhaps I'm too accustomed to compiled languages that don't require this? Or must I instead create a Python 3 class?

procedural language understanding - static vs dynamic scoping

I am having trouble understanding the answer to a homework we got back. I believe I am getting confused on the concepts of functions being "nested", but maybe that is wrong. I am looking for some help in regards to following the assignment of dynamic and static scoping values from the following code.
x : integer -- global
procedure set_x(n : integer)
x := n
end
procedure print_x
write_integer(x)
end
procedure first
set_x(1)
print_x
end
procedure second
x : integer
set_x(2)
print_x
end
// program starts here
set_x(0)
first()
print_x
second()
print_x
Static Scoping Output: 1122
Dynamic Scoping Output: 1121
My thoughts as I go through each one:
Static:
Run set_x(0), this makes a local variable due to the parameter of n, but since we set x to n without declaring x locally (int x =..) we then update the global x to 0.
Run first(), which does set_x(1), which following the same logic updates x to 1 globally. we then run print_x within first which prints the global x of 1.
Run print_x, which just re-prints 1.
Run second() we locally declare x and run set_x(2), which goes updates 2 to n. (because of the set, not the second procedure, right? We then run its print_x procedure which prints the 2.
Run print_x which again just dumps out the 2.
Resulting in 1122
Dynamic (more confused on this one)
Run set_x(0) which sets the x and global x to 0.
Run first() we hit set_x again and update x to 1. We print 1.
Run print_x We re-print 1.
Run second() We locally make x, we run set_x(2), and set global x to 2. We then print 2.
Run print_x Finally we re-print again and here is where I guessed 2, but the answer should 1.
My guess 1122, actual answer is 1121
I am confused on that last part of the dynamic and why it is a 1, and not a 2.
It's kind of hard to follow your reasoning in some places, because you don't say which x you think is being printed or updated, and that's pretty much the whole ball of wax.
The big thing to remember is that static scoping (also called lexical scoping) is fully determined at compile-time. Where something is defined determines its static scope.
Dynamic scoping is of course the converse; it's determined at run-time. Where something executes determines its dynamic scope.
So, take a look at the set_x procedure. It has no local x of its own, and it's defined in the global scope, so under static scoping, it can only ever update the global x. This is true no matter where it is called, even within the second procedure.
Under dynamic scoping, however, the set_x call within second updates the x which is local to second, leaving the global x unchanged.
Notice that the very last print_x call will always print the global x, regardless of the scoping rules (because the print_x procedure is defined in the global scope, and the call to print_x is executed in the global scope). So the difference is that with static scoping, global x is 2 at the end of the program; but with dynamic scoping, global x is 1.

Can Python use a functions default parameter when an inline if fails when calling it?

If I have a variable that has a value I don't want passed to a function, is it possible to do it without several ifs, especially if there are several variables that may or may not need to be passed in?
Take the following:
def test(param=""):
...do stuff
x = None
test(x if x else ?)
^
What can i put here so it
defaults to the default in
the function definition?
If this isn't possible, is there a quick way of doing this when there are multiple variables that may or may not need to be passed in rather than a lot of ifs?
Basic answer:
if(x): test(x)
else: test()
With *args you can pass in as many variables as you want but I don't think that will help you. The best I can think of is multiple ifs (Python doesn't allow overloading unfortunately).
That would look like:
if x:
if y:
if z: test(x,y,z)
else: test(x,y)
else: test(x)
else: test()
The reason you can't call test(x,z) or test(y) for example is because your method assumes a certain order in the signature so you wouldn't be able to specify which arg you are passing in at function call. In Java you could do it with overloading and different argument types, but not here afaik.

Resources