def __init__ question in a class definition rephrased
Steven Bethard
steven.bethard at gmail.com
Mon Feb 7 18:39:56 EST 2005
Jeffrey Borkent wrote:
> what is the significance ( if any ) of the __ in these self.xxxxxx
> assignments.
Variables with preceding __ are a vague attempt to avoid some types of
name collisions in inheritance hierarchies. Any name that starts with a
__ will be mangled by prefixing it with _<class-name>:
py> class C(object):
... def __init__(self, x):
... self.__type = type(x)
... self.x = x
...
py> C(1).__dict__
{'_C__type': <type 'int'>, 'x': 1}
py> class D(C):
... def __init__(self, x):
... super(D, self).__init__(x)
... self.__type = D
...
py> D(1).__dict__
{'_C__type': <type 'int'>, 'x': 1, '_D__type': <class '__main__.D'>}
Note that the D object has two different __type attributes -- one
mangled for type C and one mangled for type D.
While the intent of __ variables is to allow you to not worry about the
names given to "private" attributes of a class when you inherit from
that class, it doesn't actually achieve this in all cases -- you'll
still have problems if you inherit from two classes with the same names
that use the same __ attribute:
---------- a.py ----------
class A(object):
pass
---------- b.py ----------
import a
class X(a.A):
def __init__(self):
self.__x = 'b.X.__x'
super(X, self).__init__()
---------- c.py ----------
import a
class X(a.A):
def __init__(self):
self.__x = 'c.X.__x'
super(X, self).__init__()
---------- d.py ----------
import b, c
class D(b.X, c.X):
pass
--------------------------
py> import d
py> d.D().__dict__
{'_X__x': 'c.X.__x', '_A__x': 'A'}
Note that the D object has two __x attributes, not three, like it
should. Code in b.py which depends on the __x attribute is now broken
because __x should should have the value 'b.X.__x' but instead it has
the value from the c module, 'c.X.__x'.
The solution to this is to have names mangled with their module name as
well, but that's backwards incompatible, so Python's not likely to
change that way.
My general feeling here is that "we're all consenting adults", and that
__ is probably not helpful in most cases. If you simply don't want the
attribute shown by, say, pydoc, prefixing a single underscore should be
sufficient and doesn't invoke the name-mangling.
STeVe
More information about the Python-list
mailing list