PythonScope

ThoughtStorms Wiki

Context: PythonLanguage

print("""

Scope demo in Python

the x bound in the scope of f is visible within y

but is not the same as the x bound at the global scope

x = 4 y = 3 def f(x) : def g(y) : print("in g, x is %s" % x) print("in g, y is %s" % y) return x * y print("in f, x is %s" % x) return g

print("global x is %s, y is %s"%(x,y)) print("calculating .... the result is %s "% f(5)(6)) print("global x is %s, y is %s"%(x,y))

>> """)

x = 4 y = 3 def f(x) : def g(y) : print("in g, x is %s" % x) print("in g, y is %s" % y) return x * y print("in f, x is %s" % x) return g

print("global x is %s, y is %s"%(x,y)) print("calculating .... the result is %s "% f(5)(6)) print("global x is %s, y is %s"%(x,y))

print("""

what you can't do in python is assign to the captured variable x inside function g

that will give an error

there isn't an explicit "upvar" but as a workaround you can use global,

but that means something different, and makes you work with global vars,

which isn't ideal

So it's best to treat variables captured in closures as immutable

which is actually a good thing anyway, because updating them

can lead to a world of confusion and pain

If you REALLY want mutable variables in a context which can be passed around

It's better to just use a class and do things the Object Oriented way

which is more explicit and easy for people to understand

class F : def init(self,x) : self.x = x print("in F, x is %s" % self.x)

def updateX(self,x) :
    self.x = x
    print("in F, x is now %s" % self.x)
    return self
    
def calcWithY(self,y) :
    print("in calc, x is %s" % self.x)
    print("in calc, y is %s" % y)        
    return self.x * y
    

print("oo result is %s " % F(9).updateX(5).calcWithY(6)) print("global x is %s, y is %s"%(x,y))

>> """)

class F : def init(self,x) : self.x = x print("in F, x is %s" % self.x)

def updateX(self,x) :
    self.x = x
    print("in F, x is now %s" % self.x)
    return self
    
def calcWithY(self,y) :
    print("in calc, x is %s" % self.x)
    print("in calc, y is %s" % y)        
    return self.x * y
    

print("oo result is %s " % F(9).updateX(5).calcWithY(6)) print("global x is %s, y is %s"%(x,y))

print("""

Python makes a good trade-off here, I think

Closures are more concise and arguably more expressive

But less explicit and so somewhat harder to understand

Immutability makes things easier to understand

So immutable captured variables in closures buys

ease of understanding at the cost of reduced power

And if you really need mutability, python forces you to use OO

Which makes things more explicit and familiar

particularly because of Python's self notation

You can't confuse self.x with any x's that are floating around the global namespace

""")

No Backlinks