I encountered a strange issue while using python. consider the below code:
class Foo:
__bar=None
foo=Foo()
foo.bar=10
print(foo.bar)
I beleive I should get an error here. But I get the output as 10. I get the same output even if I change the code as:
foo=Foo()
foo.__bar=10
print(foo.__bar)
can someone explain why I am not getting an error here? Also what should I do to get an error? Edited for additional clarification:
class Foo:
def __init__(self):
self.__bar=10
def get_bar(self):
return self.__bar
foo=Foo()
foo.__bar=20
print(foo.__bar)
print(foo.get_bar())
Can someone explain why I am getting the answer as 20 and 10? I thought I will get an error for trying to access a private instance variable outside the class. Thanks for the help.
First of all, you should read the answers to the related quesion.
Second of all, don't confuse between class-members and instance members. Your definition of the class Foo
includes a class member named __bar
, but assigning to foo.__bar
adds an instance-member which overshadows it (and not overwrites it). Those are different things.
Now, when you assign (or in general, access) a leading-double-underscore attribute from "outside" (in your example, using foo.__bar
), the name does not get mangaled, and everything works without extra magic. However, the standard way of accessing leading-double-underscore attributes is from within methods of the class (using self.__bar
), and that is when the magic happens.
To demonstrate:
class Foo(object): pass
f = Foo()
foo.__bar = 10
foo.__bar
=> 10
foo.__dict__.keys()
=> dict_keys(['__bar'])
class Foo(object):
def __init__(self):
self.__bar = 10
foo = Foo()
foo.__dict__.keys()
=> dict_keys(['_Foo__bar']) # mangaled!
foo.__bar # cannot access from "outside"
=> AttributeError