Call nested Python 3 nested function from parent function - python-3.x

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?

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.

Declaring variables inside a function python

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

How a function in python can access the values which are declared outside its block and never passed as arguments during its call?

I have written a Python code in which a function without parameters can access the variable declared outside its scope. I want to know how Python interpreter can access this variable without giving any error like other programming languages(e.g. JAVA).
# Code 1:
def A():
# count accessed inside function
print(count)
# count declared outside function A
count = 23
A()
Output of code 1:
23
There is a bonus question also. In Python, if we declare any variable inside the loop then how it can used outside the loop. Because, as we know that the scope of any variable will remain under the block in which it is defined.
# Code 2:
for i in range(1):
# num declared inside for loop block
num = 23
# num can be accessed outside for loop block.
print(num)
Output of code 2: 23
Variable scope is inside-out. When you call a variable from inside a local scope like a function, first Python checks if there's a variable with that name in the local scope. If it doesn't find one, it expands the scope it checks in to the next outer scope. In your case, this is the global scope, the top-most level of scope. Declaring something absent of any context like a function or method defaults to the global scope, so that's where count lives.
If you want to be clear about which count it is you're referencing, you can add nonlocal count or global count to your function definition, making it explicit that you're referencing the a different scope.
Bonus question -- You can't reference a locally-scoped variable outside of its scope, so it doesn't work in reverse, sorry. However in your example you're using a loop, which does not have its own scope in Python (but Julia does, so if you ever make that switch heads up).

Calling functions with variables multiple times

I'm making a program for a school project and I'm having an issue.
I have defined a function called DidThisWork like so:
def DidThisWork():
global DidThisWork
DidThisWork = input('\n\nDid this solution work? - ').lower()
Throughout my code, I want to call this function multiple times, however, I'm not able to. Is there a way, to call it multiple times, and like reset the DidThisWork variable inside the function after I used it in if statements?
You define a function def DidThisWork(): then within that very function you overwrite the newly created DidThisWork variable (which points to the function) to the result of your input(..) call.
So at the first call to DidThisWork(), the DidThisWork variable no longer points to the function, rather to the string returned by input(...).
If you rename either the function or the variable storing the string returned by input() it should work.
By the way, there are some naming conventions in Python you may want to look into https://www.python.org/dev/peps/pep-0008/#id30. Typically you'd use snake_case instead of camelCase and not only start a class with an upper case letter
worked = None
def did_this_work():
global worked
worked = input('\n\nDid this solution work? - ').lower()
print(worked)
did_this_work()
print(worked)
did_this_work()
print(worked)

How to modify immutable objects passed as **arguments in functions with Python3 the elegant way?

I am not sure what the problem is here, so I don't really know how I should call the subject for that question. Please offer a better subject if you know.
The code below is a extrem simplified example of the original one. But it reproduce the problem very nice. After the call of test() foo should be sieben.
I think I didn't know some special things about scopes of variables in Python. This might be a very good problem to learn more about that. But I don't know on which Python topic I should focus here to find a solution for my own.
#!/usr/bin/env python3
def test(handlerFunction, **handlerArgs):
handlerFunction(**handlerArgs)
def myhandler(dat):
print('dat={}'.format(dat))
dat = 'sieben'
print('dat={}'.format(dat))
foo = 'foo'
test(myhandler, dat=foo)
print('foo={}'.format(foo))
Of course I could make foo a global variable. But that is not the goal. The goal is to carry this variable inside and through sub-functions of different levels and bring the result back. In the original code I use some more complexe data structures with **handlerArgs.
A solution could be to use a list() as an mutable object holding the immutable one. But is this really elegant or pythonic?
#!/usr/bin/env python3
def test(handlerFunction, **handlerArgs):
handlerFunction(**handlerArgs)
def myhandler(dat):
print('dat={}'.format(dat))
# MODIFIED LINE
dat[0] = 'sieben'
print('dat={}'.format(dat))
# MODIFIED LINE
foo = ['foo']
test(myhandler, dat=foo)
print('foo={}'.format(foo))
The ** syntax has nothing to do with this. dat is local to myhandler, and assigning it doesn't change the global variable with the same name. If you want to change the module variable from inside the function, declare the variable as global at the beginning of the function body:
def myhandler(): # you don't need to pass dat as argument
global dat
print('dat={}'.format(dat))
dat = 'sieben'
print('dat={}'.format(dat))
Here's a relevant portion from the docs:
If a name binding operation occurs anywhere within a code block, all uses of the name within the block are treated as references to the current block. This can lead to errors when a name is used within a block before it is bound. This rule is subtle. Python lacks declarations and allows name binding operations to occur anywhere within a code block. The local variables of a code block can be determined by scanning the entire text of the block for name binding operations.
If the global statement occurs within a block, all uses of the name specified in the statement refer to the binding of that name in the top-level namespace. Names are resolved in the top-level namespace by searching the global namespace, i.e. the namespace of the module containing the code block, and the builtins namespace, the namespace of the module builtins. The global namespace is searched first. If the name is not found there, the builtins namespace is searched. The global statement must precede all uses of the name.
After your edit the question reads as: "how do I mutate an immutable object?"
Well, I think you've guessed it: you don't. Using a mutable object in this manner seems reasonable to me.

Resources