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
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to