derived / base class name conflicts

Discussion in 'Python' started by christopherlmarshall@yahoo.com, Nov 10, 2005.

  1. Guest

    Suppose you want to write a subclass of some existing class you are
    importing from a module you didn't write and that you don't want to
    study the internals of, and you want to define a data member i in your
    constructor.

    As in the following:

    from module1 import A

    class B(A):
    def __init__(self):
    A.__init__(self)
    self.i= 0
    b= B()

    Now, 'i' might have already been defined by A or by the call to
    A.__init__() so if you define it without knowing that, you could be
    changing the behavior of A's methods in unknown ways, which is
    obviously a bad thing.

    One way to avoid this is to run the following program to clear the name
    'i' first:

    from module1 import A
    a= A()
    print a.i

    If you get an AttributeError, you know the name 'i' is safe to use. If
    you actually get some sort of report from the print statement, then you
    will know that 'i' is not safe to use.

    This strikes me as a rather odd procedure to go through, but I don't
    see any way around it.

    It there some other way to handle this issue?

    Do I actually need to study the sources for / implementation of
    Tkinter.Canvas before I can safely subclass it (and assign attributes
    to an instance of the subclass) or clear attribute names as I outlined
    above?

    Chris Marshall
     
    , Nov 10, 2005
    #1
    1. Advertising

  2. Fredrik Lundh, Nov 10, 2005
    #2
    1. Advertising

  3. This should prove most enlightening:

    import Tkinter
    dir(Tkinter.Canvas)



    On 10 Nov 2005 14:53:04 -0800,
    <> wrote:
    > Suppose you want to write a subclass of some existing class you are
    > importing from a module you didn't write and that you don't want to
    > study the internals of, and you want to define a data member i in your
    > constructor.
    >
    > As in the following:
    >
    > from module1 import A
    >
    > class B(A):
    > def __init__(self):
    > A.__init__(self)
    > self.i= 0
    > b= B()
    >
    > Now, 'i' might have already been defined by A or by the call to
    > A.__init__() so if you define it without knowing that, you could be
    > changing the behavior of A's methods in unknown ways, which is
    > obviously a bad thing.
    >
    > One way to avoid this is to run the following program to clear the name
    > 'i' first:
    >
    > from module1 import A
    > a= A()
    > print a.i
    >
    > If you get an AttributeError, you know the name 'i' is safe to use. If
    > you actually get some sort of report from the print statement, then you
    > will know that 'i' is not safe to use.
    >
    > This strikes me as a rather odd procedure to go through, but I don't
    > see any way around it.
    >
    > It there some other way to handle this issue?
    >
    > Do I actually need to study the sources for / implementation of
    > Tkinter.Canvas before I can safely subclass it (and assign attributes
    > to an instance of the subclass) or clear attribute names as I outlined
    > above?
    >
    > Chris Marshall
    >
    > --
    > http://mail.python.org/mailman/listinfo/python-list
    >



    --
    Steve Juranich
    Tucson, AZ
    USA
     
    Steve Juranich, Nov 10, 2005
    #3
  4. Guest

    Steve Juranich wrote:
    > This should prove most enlightening:
    >
    > import Tkinter
    > dir(Tkinter.Canvas)
    >
    >


    Huh?

    Chris Marshall
     
    , Nov 11, 2005
    #4
  5. Guest

    Fredrik Lundh wrote:
    > wrote:
    >
    > > Now, 'i' might have already been defined by A or by the call to
    > > A.__init__() so if you define it without knowing that, you could be
    > > changing the behavior of A's methods in unknown ways, which is
    > > obviously a bad thing.

    >
    > http://docs.python.org/tut/node11.html#SECTION0011600000000000000000
    >
    > </F>


    I see. Thanks for the link.

    So putting two underscores in front of an instance variable (or any
    identifier used inside the scope of a class statement) invokes a name
    mangling mechanism ( __x becomes __classname_x internally)

    so the following would not result in any conflicts

    class A:
    def __init__(self):
    self.__i= 0

    class B(A):
    def __init__(self):
    A.__init__(self)
    self.__i= 1

    Is it commonplace to use underscores when defining derived class
    instance variables, or is this considered against the grain of python?

    Chris Marshall
     
    , Nov 11, 2005
    #5
  6. Ben Finney Guest

    wrote:
    > Suppose you want to write a subclass of some existing class you are
    > importing from a module you didn't write and that you don't want to
    > study the internals of


    No need to study its internals. Fire up a Python interpreter and
    inspect its outside:

    >>> import foomodule
    >>> dir(foomodule.FooClass)


    Any attributes named there should be avoided in your subclasses if you
    don't want to clobber existing behaviour.

    --
    \ "Those who will not reason, are bigots, those who cannot, are |
    `\ fools, and those who dare not, are slaves." -- "Lord" George |
    _o__) Gordon Noel Byron |
    Ben Finney
     
    Ben Finney, Nov 11, 2005
    #6
  7. wrote:
    (snip)
    > So putting two underscores in front of an instance variable (or any
    > identifier used inside the scope of a class statement) invokes a name
    > mangling mechanism


    (snip)

    > Is it commonplace to use underscores


    I assume you mean double underscore...

    > when defining derived class
    > instance variables,
    > or is this considered against the grain of python?


    I don't know if it's 'commonplace', but that's something I only do when
    I absolutely want to protect a given attribute of a base class from
    being accidentally overriden by a derived class. Else I use the usual
    convention ('_name' => implementation, 'name' => API), and assume users
    of my code will read the documentation (or the source FWIW) before
    subclassing. Note that since 'users of my code' are mostly my coworkers
    and I, this is a quite sensible assumption !-)

    --
    bruno desthuilliers
    python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
    p in ''.split('@')])"
     
    bruno at modulix, Nov 11, 2005
    #7
  8. Guest

    I see what you mean now.

    It would indeed be enlightening if I wanted to study the internals of
    Tkinter, and perhaps one day I will.
     
    , Nov 11, 2005
    #8
  9. Guest

    Your suggestion ('_name' -> implementation, 'name' -> API) makes sense
    as a convention between programmers that know a fair amount about each
    other's classes before using them.

    I don't think it is reasonable in general to only subclass from base
    classes you have studied the full API of, however. The double
    underscore is a decent solution to my problem.

    I imagine it must be used a lot in domains where people are making
    heavy use of third party python code.

    Chris Marshall
     
    , Nov 11, 2005
    #9
  10. <> wrote:
    ...
    > I don't think it is reasonable in general to only subclass from base
    > classes you have studied the full API of, however. The double


    I think you underestimate the level of coupling that inevitably occurs
    between base and derived classes. In general, such coupling being
    strong, knowing the full API of the base class is inevitable (although
    in some special corner-case, when you do only need to add private data,
    you may, exceptionally, get away with less knowledge).


    Alex
     
    Alex Martelli, Nov 11, 2005
    #10
  11. a écrit :
    > Your suggestion ('_name' -> implementation, 'name' -> API)


    This is not "my" convention, it's *the* (mostly agreed upon) Python
    convention. Like 'self', or CONSTANT, or a whole lot of things in Python.

    > makes sense
    > as a convention between programmers that know a fair amount about each
    > other's classes before using them.


    No need to know much. dir(modulename.ClassName) is enough.

    > I don't think it is reasonable in general to only subclass from base
    > classes you have studied the full API of, however.


    Depends on your definition of "studying the full API" !-)

    Now if your fear is to accidentally override something in the base
    class, it's just a matter of:
    print "API:"
    print [name for name in dir(modulename.ClassName) \
    if not name.startswith('_')]

    print "IMPLEMENTATION:"
    print [name for name in dir(modulename.ClassName) \
    if not name.startswith('_')]

    > The double
    > underscore is a decent solution to my problem.


    Possibly. It can also become a PITA. But it's you who know what your
    code need !-)

    > I imagine it must be used a lot in domains where people are making
    > heavy use of third party python code.


    I almost never used it (perhaps half-a-dozen times, and only in
    frameworks abstract base classes), and rarely saw it in 3rd part source
    code.
     
    Bruno Desthuilliers, Nov 13, 2005
    #11
  12. wrote:
    > so the following would not result in any conflicts
    >
    > class A:
    > def __init__(self):
    > self.__i= 0
    >
    > class B(A):
    > def __init__(self):
    > A.__init__(self)
    > self.__i= 1
    >


    Be careful here. The above won't result in any conflicts, but related
    cases, where you have two classes with the same name in different
    modules, may still result in conflicts. See my previous posts on this:

    http://groups.google.com/group/comp.lang.python/msg/503984abaee1c2b5
    http://groups.google.com/group/comp.lang.python/msg/f03183a2c01c8ecf

    However, I tend not to use double-underscore name mangling, and I don't
    think I've ever had a shadowing problem, so clearly I wouldn't have
    shadowing problems with double-underscore name mangling either...

    STeVe
     
    Steven Bethard, Nov 16, 2005
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.

Share This Page