Reputation: 61
I'm so confused with global
and immutable variable. I have this code:
class ProcessObject:
RR = 0
def b(self):
self.RR=5
print("valor: ", self.RR)
def c(self):
print("final: ", self.RR)
def d(self):
global RR
RR = 3
print("valor: ", RR)
print(RR)
proce = ProcessObject()
proce.b()
proce.c()
proce.d()
proce.c()
And it have this output:
0
value: 5
final: 5
value: 3
final: 5
But I not understand why with "c
" the value is 5 if the RR is an object immutable. And why "d
" using global no mute the value of RR
.
Upvotes: 0
Views: 128
Reputation: 61
Thank you very much!! Now I understand it. With your examples now I understand so better how python works and his context. But already remains to know for me a little question, and it is about immutability. How can I make a variable immutable? If I change his value and I call again to this variable, the value has been changed. With this code you can know what I mean say.
def e(self):
print("before calling e - ProcessObject.__dict__ : {}".format(ProcessObject.__dict__))
ProcessObject.RR = -7
print("after calling e - ProcessObject.__dict__ : {}".format(ProcessObject.__dict__))
print("=================")
And return;
=================
before calling e - ProcessObject.__dict__ : {'b': <function ProcessObject.b at 0x006850C0>, '__module__': '__main__', 'RR': 0, '__weakref__': <attribute '__weakref__' of 'ProcessObject' objects>, 'd': <function ProcessObject.d at 0x00685150>, '__doc__': None, 'e': <function ProcessObject.e at 0x00685198>, '__init__': <function ProcessObject.__init__ at 0x00685078>, 'c': <function ProcessObject.c at 0x00685108>, '__dict__': <attribute '__dict__' of 'ProcessObject' objects>}
after calling e - ProcessObject.__dict__ : {'b': <function ProcessObject.b at 0x006850C0>, '__module__': '__main__', 'RR': -7, '__weakref__': <attribute '__weakref__' of 'ProcessObject' objects>, 'd': <function ProcessObject.d at 0x00685150>, '__doc__': None, 'e': <function ProcessObject.e at 0x00685198>, '__init__': <function ProcessObject.__init__ at 0x00685078>, 'c': <function ProcessObject.c at 0x00685108>, '__dict__': <attribute '__dict__' of 'ProcessObject' objects>}
=================
before calling e - ProcessObject.__dict__ : {'b': <function ProcessObject.b at 0x006850C0>, '__module__': '__main__', 'RR': -7, '__weakref__': <attribute '__weakref__' of 'ProcessObject' objects>, 'd': <function ProcessObject.d at 0x00685150>, '__doc__': None, 'e': <function ProcessObject.e at 0x00685198>, '__init__': <function ProcessObject.__init__ at 0x00685078>, 'c': <function ProcessObject.c at 0x00685108>, '__dict__': <attribute '__dict__' of 'ProcessObject' objects>}
after calling e - ProcessObject.__dict__ : {'b': <function ProcessObject.b at 0x006850C0>, '__module__': '__main__', 'RR': -7, '__weakref__': <attribute '__weakref__' of 'ProcessObject' objects>, 'd': <function ProcessObject.d at 0x00685150>, '__doc__': None, 'e': <function ProcessObject.e at 0x00685198>, '__init__': <function ProcessObject.__init__ at 0x00685078>, 'c': <function ProcessObject.c at 0x00685108>, '__dict__': <attribute '__dict__' of 'ProcessObject' objects>}
=================
In the code of bruno desthuilliers
I have added a new function for see that, and the value of RR changes from RR=0
to RR=-7
, but I want do RR
immutable, and with that, when someone would try change the value of RR, block this action.
Upvotes: 0
Reputation: 77912
This has nothing to do with immutability... But anyway:
class ProcessObject:
# this "RR" lives in the `class` statement namespace,
# it's accessible as 'RR' in this namespace. After the
# `class` statement is executed, it becomes an attribute
# of the `ProcessObject` class, accessible as `ProcessObject.RR`,
# and thru instances as `ProcessObject().RR`.
#
RR = 0
def b(self):
# this creates an "RR" instance attribute
# on the current instance (`self`), which shadows
# the "RR" class attribute
self.RR=5
print("valor: ", self.RR)
def c(self):
print("final: ", self.RR)
def d(self):
# The two following lines creates a module-global
# name "RR", which is distinct from the two previous
# ones.
global RR
RR = 3
print("valor: ", RR)
# this prints the value of the `RR` living in the class
# statement scope - NOT the value of the yet non-existing
# global RR
print(RR)
proce = ProcessObject()
proce.b() # this creates the `proce.RR` instance attribute
proce.c()
proce.d()
proce.c()
But I not understand why with "c" the value is 5 if the RR is an object immutable.
It prints '5' because you assigned that value to proce.RR
when calling proce.b()
. You're confusing names and values... RR
is not an object, it's a name which is bound to an object. The fact that it's at one point bound to an immutable object doesn't mean you cannot rebind it to another object (mutable or not, that's irrelevant here).
And why "d" using global no mute the value of RR
And here you are confusing binding (assignment) and mutating. binding (assignment) means "make that name points to this object", mutating means "change the state of this object". An example of mutation is adding or removing an element to/from a list, or reversing a list in place.
FWIW, the call to proce.d
DO rebind (and actually bind on the first call) the module-global "RR".
You may want to run this '"extended" version of your script to find out what really happens:
print("before : globals = {}".format(globals()))
class ProcessObject:
RR = 0
print "RR defined in the class namespace - not in globals: {}".format(globals())
def __init__(self):
print("in init")
print(" self.__dict__ : {}".format(self.__dict__))
print(" ProcessObject.__dict__ : {}".format(ProcessObject.__dict__))
def b(self):
print("before calling b - self.__dict__ : {}".format(self.__dict__))
self.RR=5
print("valor: ", self.RR)
print("after calling b - self.__dict__ : {}".format(self.__dict__))
def c(self):
print("before calling c - self.__dict__ : {}".format(self.__dict__))
print("final: ", self.RR)
def d(self):
print("before calling d : globals = {}".format(globals()))
global RR
RR = 3
print("valor: ", RR)
print("after calling d : globals = {}".format(globals()))
print(RR)
print("after class statement: globals : {}".format(globals()))
proce = ProcessObject()
proce.c()
proce.b()
proce.c()
proce.d()
proce.c()
Upvotes: 1
Reputation: 160447
The function d
is going to alter (after creating it) the value of RR
in the global namespace, not self.RR
which is an instance variable; i.e you're in no way altering self.RR
.
As such, when you print RR
in d
, 3
is going to get printed, the value you've assigned to the global RR
.
If you print out self.RR
in d
too, you'll see that these are just two similar names located in a different namespace (each holding their corresponding value):
def d(self):
global RR
RR = 3
print("valor: ", RR)
print("self.RR ", self.RR)
Prints out:
valor : 3
self.RR : 5
Upvotes: 2