Reputation: 1407
I have below code
class AccountBannk:
def __init__(self,balance,holder):
self.__AccountHolder=holder
def Display_AccountHolder(self):
print "account holder is" , self.__AccountHolder
myaccount=AccountBannk(100000,"mehdiebagvand")
#print myaccount.__AccountHolder #is a error
myaccount.__AccountHolder="ali"
print myaccount.__AccountHolder #print ali
in this code AccountHolder is a private attribute
and in python we can not directly edit or print it.
if we try below code, python release a error
print myaccount.__AccountHolder
but my questions are
1-why python not release error in below code
myaccount.__AccountHolder="ali"
2-I print myaccount.__AccountHolder in end_line but python not release error
and change the value of myaccount.__AccountHolder to 'ali'
Upvotes: 1
Views: 71
Reputation: 71485
This is one of the many reasons I believe that it's way more trouble than it's worth to use __names
as "private variables". The intended use case of __names
is more to allow classes in a hierarchy to use nice(ish) names without worrying so much about what names are in use by other classes in the hierarchy, not to create "private" attributes.
For "private" attributes, just use single leading underscores (like _name
). This documents your intention that certain names are private implementation details, while others are part of the class' public interface. It doesn't prevent anyone using the "private" name, but neither do __names
because the mangling is very easy to reverse-engineer. All either of these techniques do is prevent anyone from accidentally using a name you intended to be private; they can do dodgy things, but they have to know that they're doing it. This is all you can ever get in Python; because everything is dynamic anyone can do anything at any time anyway.
So the major difference between __name
and _name
for your private internal names is that __name
will become a major PITA whenever you start wanting to use getattr
or hasattr
(even within the correct class), dynamically attach methods, or have a subclass that does want to share the "private" name. A _name
with a single underscore has no problems in any of those areas, is just as effective at documenting your intention, and is just as effective (i.e. almost completely ineffective) in preventing private names being used outside the class definition.
Upvotes: 1
Reputation: 30416
This is not a bug. When you are defining your first __AccountHolder
inside you class, Python is mangling the variable's name (making it hard to guess, but not truly private, see PEP-8). When you attach your second __AccountHolder
you are creating a new varible (with a new mangled name). Try this to see:
print myaccount.__AccountHolder
print myaccount.Display_AccountHolder()
Or add
print dir(myaccount)
Before and after you do that second assignment like so:
>>> myaccount=AccountBannk(100000,"mehdiebagvand")
>>> dir(myaccount)
['Display_AccountHolder', '_AccountBannk__AccountHolder', '__doc__', '__init__', '__module__']
>>> myaccount.__AccountHolder="ali"
>>> dir(myaccount)
['Display_AccountHolder', '_AccountBannk__AccountHolder', '__AccountHolder', '__doc__', '__init__', '__module__']
And as for the name mangling, here it is from the documentation:
__double_leading_underscore: when naming a class attribute, invokes name mangling (inside class FooBar, __boo becomes FooBar_boo; see below).
Upvotes: 3