derived / base class name conflicts

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • christopherlmarshall@yahoo.com

    #1

    derived / base class name conflicts

    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

  • Steve Juranich

    #2
    Re: derived / base class name conflicts

    This should prove most enlightening:

    import Tkinter
    dir(Tkinter.Can vas)



    On 10 Nov 2005 14:53:04 -0800, christopherlmar shall@yahoo.com
    <christopherlma rshall@yahoo.co m> wrote:[color=blue]
    > 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
    >[/color]


    --
    Steve Juranich
    Tucson, AZ
    USA

    Comment

    • Fredrik Lundh

      #3
      Re: derived / base class name conflicts

      christopherlmar shall@yahoo.com wrote:
      [color=blue]
      > 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.[/color]



      </F>



      Comment

      • christopherlmarshall@yahoo.com

        #4
        Re: derived / base class name conflicts

        Steve Juranich wrote:[color=blue]
        > This should prove most enlightening:
        >
        > import Tkinter
        > dir(Tkinter.Can vas)
        >
        >[/color]

        Huh?

        Chris Marshall

        Comment

        • christopherlmarshall@yahoo.com

          #5
          Re: derived / base class name conflicts


          Fredrik Lundh wrote:[color=blue]
          > christopherlmar shall@yahoo.com wrote:
          >[color=green]
          > > 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.[/color]
          >
          > http://docs.python.org/tut/node11.ht...00000000000000
          >
          > </F>[/color]

          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

          Comment

          • Ben Finney

            #6
            Re: derived / base class name conflicts

            christopherlmar shall@yahoo.com wrote:[color=blue]
            > 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[/color]

            No need to study its internals. Fire up a Python interpreter and
            inspect its outside:
            [color=blue][color=green][color=darkred]
            >>> import foomodule
            >>> dir(foomodule.F ooClass)[/color][/color][/color]

            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

            Comment

            • bruno at modulix

              #7
              Re: derived / base class name conflicts

              christopherlmar shall@yahoo.com wrote:
              (snip)[color=blue]
              > 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[/color]

              (snip)
              [color=blue]
              > Is it commonplace to use underscores[/color]

              I assume you mean double underscore...
              [color=blue]
              > when defining derived class
              > instance variables,
              > or is this considered against the grain of python?[/color]

              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 'onurb@xiludom. gro'.split('@')])"

              Comment

              • christopherlmarshall@yahoo.com

                #8
                Re: derived / base class name conflicts

                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.

                Comment

                • christopherlmarshall@yahoo.com

                  #9
                  Re: derived / base class name conflicts

                  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

                  Comment

                  • Alex Martelli

                    #10
                    Re: derived / base class name conflicts

                    <christopherlma rshall@yahoo.co m> wrote:
                    ...[color=blue]
                    > 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[/color]

                    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

                    Comment

                    • Bruno Desthuilliers

                      #11
                      Re: derived / base class name conflicts

                      christopherlmar shall@yahoo.com a écrit :[color=blue]
                      > Your suggestion ('_name' -> implementation, 'name' -> API)[/color]

                      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.
                      [color=blue]
                      > makes sense
                      > as a convention between programmers that know a fair amount about each
                      > other's classes before using them.[/color]

                      No need to know much. dir(modulename. ClassName) is enough.
                      [color=blue]
                      > I don't think it is reasonable in general to only subclass from base
                      > classes you have studied the full API of, however.[/color]

                      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 ('_')]
                      [color=blue]
                      > The double
                      > underscore is a decent solution to my problem.[/color]

                      Possibly. It can also become a PITA. But it's you who know what your
                      code need !-)
                      [color=blue]
                      > I imagine it must be used a lot in domains where people are making
                      > heavy use of third party python code.[/color]

                      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.

                      Comment

                      • Steven Bethard

                        #12
                        Re: derived / base class name conflicts

                        christopherlmar shall@yahoo.com wrote:[color=blue]
                        > 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
                        >[/color]

                        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:




                        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

                        Comment

                        • Steven Bethard

                          #13
                          Re: derived / base class name conflicts

                          christopherlmar shall@yahoo.com wrote:[color=blue]
                          > 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
                          >[/color]

                          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:




                          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

                          Comment

                          Working...