How can I set a class variable from inside a function inside another function?
var.py
class A:
    def __init__(self):
        self.a = 1
        self.b = 2
        self.c = 3
    def seta(self):
        def afunction():
            self.a = 4
        afunction()
    def geta(self):
        return self.a
run.py
cA = A()
print cA.a
cA.seta()
print cA.a
print cA.geta()
python run.py
1
1
1
why does a not equal 4 and how can I make it equal 4?
Edit:
Thanks everyone - sorry, I just saw now. I accidentally was off by a _ in one of my names.... so my scope is actually all ok.
A function defined inside another function is called a nested function. Nested functions can access variables of the enclosing scope. In Python, these non-local variables are read-only by default and we must declare them explicitly as non-local (using nonlocal keyword) in order to modify them.
The scope of a nested function is inside the enclosing function, i.e. inside one of the constituent blocks of that function, which means that it is invisible outside that block and also outside the enclosing function. A nested function can access other local functions, variables, constants, types, classes, etc.
Inner functions, also known as nested functions, are functions that you define inside other functions. In Python, this kind of function has direct access to variables and names defined in the enclosing function.
A function which is defined inside another function is known as inner function or nested functio n. Nested functions are able to access variables of the enclosing scope. Inner functions are used so that they can be protected from everything happening outside the function.
The problem is that there are multiple self variables.  The argument passed into your inner function overwrites the scope of the outer.
You can overcome this by removing the self parameter from the inner function, and making sure you call that function in some way.
class A:
    def __init__(self):
        self.a = 1
        self.b = 2
        self.c = 3
    def seta(self):
        def afunction():  # no self here
            self.a = 4
        afunction()       # have to call the function
    def geta(self):
        return self.a
                        As others have mentioned, afunction is never called.  You could do something like this:
class A:
    def __init__(self):
        self.a = 1
    def seta(self):
        def afunction(self):
            self.a = 4
        afunction(self)
    def geta(self):
        return self.a
a = A()
print a.a
a.seta()
print a.a
Here we actually call afunction and explicitly pass it self, but this is a rather silly way to set the attribute a -- especially when we can do it explicitly without the need for getters or setters:  a.a = 4
Or you could return the function:
def seta(self):
    def afunction(): #Don't need to pass `self`.  It gets picked up from the closure
        self.a = 4
    return afunction
and then in the code:
a = A()
a.seta()()  #the first call returns the `afunction`, the second actually calls it.
                        Inside seta, you define a function
    def afunction(self):
        self.a = 4
...that would set self.a to 4 if it would ever be called. But it's not called anywhere, so a is unchanged.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With