Last active
October 11, 2021 15:27
-
-
Save interstar/3ae1602404c0186352ea2f873224c252 to your computer and use it in GitHub Desktop.
Python scope test
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
""") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment