1

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'

6
  • Change it to ali and then call Display_AccountHolder(). Commented Mar 18, 2013 at 21:33
  • Display_AccountHolder() work good but my qestion is another Commented Mar 18, 2013 at 21:35
  • Well, what does Display_AccountHolder() print out? Commented Mar 18, 2013 at 21:36
  • print account holder ismehdiebagvand Commented Mar 18, 2013 at 21:37
  • Exactly. You created a new attribute with the value of ali, but left the "private" one intact. Commented Mar 18, 2013 at 21:38

2 Answers 2

3

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).

Sign up to request clarification or add additional context in comments.

Comments

1

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.