Search code examples
pythonprivate

No error for Python private variable


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.


Solution

  • 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