Stylistic question about inheritance

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Andrew Koenig

    #1

    Stylistic question about inheritance

    Suppose I want to define a class hierarchy that represents expressions, for
    use in a compiler or something similar.

    We might imagine various kinds of expressions, classified by their top-level
    operator (if any). So, an expression might be a primary (which, in turn,
    might be a variable or a constant), a unary expression (i.e. the result of
    applying a unary operator to an expression), a binary expression, and so on.

    If I were solving such a problem in C++, I would define a base class for all
    expressions, then derive the various kinds of expression classes from that
    base class. However, I would not anticipate ever creating objects of the
    base class, so I would make it abstract.

    In Python, I can imagine doing the same thing:

    class Expr(object):
    pass

    class UnaryExpr(Expr) :
    # ...

    class BinaryExpr(Expr ):
    # ...

    and so on. However, although I don't have a choice in C++ about having a
    base class--you can't use dynamic binding without it--in Python I do have
    that choice. That is, I don't need to have the base class at all unless I
    want to have some operations that are common to all derived classes.

    Of course, there are reasons to have a base class anyway. For example, I
    might want it so that type queries such as isinstance(foo, Expr) work. My
    question is: Are there other reasons to create a base class when I don't
    really need it right now?


  • Carl Banks

    #2
    Re: Stylistic question about inheritance


    Andrew Koenig wrote:
    [snip][color=blue]
    > Of course, there are reasons to have a base class anyway. For[/color]
    example, I[color=blue]
    > might want it so that type queries such as isinstance(foo, Expr)[/color]
    work. My[color=blue]
    > question is: Are there other reasons to create a base class when I[/color]
    don't[color=blue]
    > really need it right now?[/color]

    Well, Python seems to get along fine without the ability to do
    isinstance(foo, file_like_objec t); probably better off in the end for
    it. So I'd say you should generally not do it. Inheritence is for
    when different classes need to share functionality.


    --
    CARL BANKS

    Comment

    • Martin v. Löwis

      #3
      Re: Stylistic question about inheritance

      Andrew Koenig wrote:[color=blue]
      > Of course, there are reasons to have a base class anyway. For example, I
      > might want it so that type queries such as isinstance(foo, Expr) work. My
      > question is: Are there other reasons to create a base class when I don't
      > really need it right now?[/color]

      You would normally try to avoid type queries, and rely on virtual
      methods instead, if possible. It seems likely for the application
      that code can be shared across different subclasses, for example,
      you might be able to define

      def Expr:
      def __str__(self):
      return '%s(%s)' % (self.__class__ .__name__,
      ", ".join(map( str, self.operands() ))

      requiring you only to implement .operands() in the subclasses.

      If you can anticipate such common code, it is easier to add
      a base class right away. If you cannot think of a specific
      use case, there is little point in having a common base class.

      Regards,
      Martin

      Comment

      • Andrew Koenig

        #4
        Re: Stylistic question about inheritance

        "Carl Banks" <invalidemail@a erojockey.com> wrote in message
        news:1112300127 .449931.146470@ o13g2000cwo.goo glegroups.com.. .
        [color=blue]
        > Well, Python seems to get along fine without the ability to do
        > isinstance(foo, file_like_objec t); probably better off in the end for
        > it. So I'd say you should generally not do it. Inheritence is for
        > when different classes need to share functionality.[/color]

        That's really the question: Is it for when they need to share
        functionality, or when they are conceptually related in ways that might lead
        to shared functionality later?


        Comment

        • Lonnie Princehouse

          #5
          Re: Stylistic question about inheritance

          If you try this sort of inheritance, I'd recommend writing down the
          formal grammar before you start writing classes. Don't try to define
          the grammar through the inheritance hierarchy; it's too easy to
          accidentally build a hierarchy that can't be translated into a
          single-pass-parsable grammar...

          I usually skip the inheritance and make everything an instance of the
          same class, e.g.

          class ASTNode(object) : ...

          class Stmt(ASTNode): ...
          class Expr(ASTNode): ...
          class UnaryExpr(ASTNo de): ...
          class BinaryExpr(ASTN ode): ...

          or you could dynamically generate classes with inheritance based on a
          grammar definition

          Comment

          • Andrew Koenig

            #6
            Re: Stylistic question about inheritance

            ""Martin v. Löwis"" <martin@v.loewi s.de> wrote in message
            news:424C5B09.9 090006@v.loewis .de...
            [color=blue]
            > You would normally try to avoid type queries, and rely on virtual
            > methods instead, if possible.[/color]

            Of course.
            [color=blue]
            > It seems likely for the application
            > that code can be shared across different subclasses, for example,
            > you might be able to define
            >
            > def Expr:
            > def __str__(self):
            > return '%s(%s)' % (self.__class__ .__name__,
            > ", ".join(map( str, self.operands() ))
            >
            > requiring you only to implement .operands() in the subclasses.[/color]

            Indeed.
            [color=blue]
            > If you can anticipate such common code, it is easier to add
            > a base class right away. If you cannot think of a specific
            > use case, there is little point in having a common base class.[/color]

            So, for example, you don't think it's worth including the base class as a
            way of indicating future intent?


            Comment

            • Andrew Koenig

              #7
              Re: Stylistic question about inheritance

              "Lonnie Princehouse" <finite.automat on@gmail.com> wrote in message
              news:1112300578 .456411.274110@ f14g2000cwb.goo glegroups.com.. .
              [color=blue]
              > If you try this sort of inheritance, I'd recommend writing down the
              > formal grammar before you start writing classes. Don't try to define
              > the grammar through the inheritance hierarchy; it's too easy to
              > accidentally build a hierarchy that can't be translated into a
              > single-pass-parsable grammar...[/color]

              Understood. I was using expression trees as a contrived example, and really
              want to know about the Python community's stylistic preferences for defing
              such hierarchies that don't absolutely need a root.
              [color=blue]
              > I usually skip the inheritance and make everything an instance of the
              > same class, e.g.
              >
              > class ASTNode(object) : ...
              >
              > class Stmt(ASTNode): ...
              > class Expr(ASTNode): ...
              > class UnaryExpr(ASTNo de): ...
              > class BinaryExpr(ASTN ode): ...[/color]

              Eh? There's still inheritance here: Everything is derived from ASTNode. I
              understand that there is a separate design issue whether to make the
              hierarchy deep or shallow, but it's still a hierarchy.



              Comment

              • Irmen de Jong

                #8
                Re: Stylistic question about inheritance

                Andrew Koenig wrote:[color=blue]
                > "Lonnie Princehouse" <finite.automat on@gmail.com> wrote in message
                > news:1112300578 .456411.274110@ f14g2000cwb.goo glegroups.com.. .
                >
                >[color=green]
                >>If you try this sort of inheritance, I'd recommend writing down the
                >>formal grammar before you start writing classes. Don't try to define
                >>the grammar through the inheritance hierarchy; it's too easy to
                >>accidentall y build a hierarchy that can't be translated into a
                >>single-pass-parsable grammar...[/color]
                >
                >
                > Understood. I was using expression trees as a contrived example, and really
                > want to know about the Python community's stylistic preferences for defing
                > such hierarchies that don't absolutely need a root.[/color]

                I have used empty or near-empty base classes to be some sort of
                class 'tag' for the derived classes.
                Much like Java's Serializable interface; it adds nothing on
                a functional level but you can check if a class has a 'tag'
                by checking if it is an instance of the base class.
                I don't know if this is good style in Python but I tend
                to use it sometimes (probably because I do Java at work ;-)

                --Irmen

                Comment

                • Donn Cave

                  #9
                  Re: Stylistic question about inheritance

                  In article
                  <P_Y2e.493283$w 62.145022@bgtns c05-news.ops.worldn et.att.net>,
                  "Andrew Koenig" <ark@acm.org> wrote:
                  [color=blue]
                  > "Carl Banks" <invalidemail@a erojockey.com> wrote in message
                  > news:1112300127 .449931.146470@ o13g2000cwo.goo glegroups.com.. .
                  >[color=green]
                  > > Well, Python seems to get along fine without the ability to do
                  > > isinstance(foo, file_like_objec t); probably better off in the end for
                  > > it. So I'd say you should generally not do it. Inheritence is for
                  > > when different classes need to share functionality.[/color]
                  >
                  > That's really the question: Is it for when they need to share
                  > functionality, or when they are conceptually related in ways that might lead
                  > to shared functionality later?[/color]

                  No -- inheritance is for implementation, not to express conceptual
                  relationship.

                  Donn Cave, donn@u.washingt on.edu

                  Comment

                  • Stefan Seefeld

                    #10
                    Re: Stylistic question about inheritance

                    Andrew Koenig wrote:
                    [color=blue]
                    > Of course, there are reasons to have a base class anyway. For example, I
                    > might want it so that type queries such as isinstance(foo, Expr) work. My
                    > question is: Are there other reasons to create a base class when I don't
                    > really need it right now?[/color]

                    Coming from C++ myself, I still prefer to use inheritance even if Python
                    doesn't force me to do it. It's simply a matter of mapping the conceptual
                    model to the actual design/implementation, if ever possible.

                    Regards,
                    Stefan


                    Comment

                    • Martin v. Löwis

                      #11
                      Re: Stylistic question about inheritance

                      Andrew Koenig wrote:[color=blue]
                      > So, for example, you don't think it's worth including the base class as a
                      > way of indicating future intent?[/color]

                      No. In this respect, I believe in XP: refactor when the need comes up,
                      but not before.

                      Regards,
                      Martin

                      Comment

                      • Bengt Richter

                        #12
                        Re: Stylistic question about inheritance

                        On Thu, 31 Mar 2005 20:24:08 GMT, "Andrew Koenig" <ark@acm.org> wrote:
                        [color=blue]
                        >""Martin v. Löwis"" <martin@v.loewi s.de> wrote in message
                        >news:424C5B09. 9090006@v.loewi s.de...
                        >[color=green]
                        >> You would normally try to avoid type queries, and rely on virtual
                        >> methods instead, if possible.[/color]
                        >
                        >Of course.
                        >[color=green]
                        >> It seems likely for the application
                        >> that code can be shared across different subclasses, for example,
                        >> you might be able to define
                        >>
                        >> def Expr:
                        >> def __str__(self):
                        >> return '%s(%s)' % (self.__class__ .__name__,
                        >> ", ".join(map( str, self.operands() ))
                        >>
                        >> requiring you only to implement .operands() in the subclasses.[/color]
                        >
                        >Indeed.
                        >[color=green]
                        >> If you can anticipate such common code, it is easier to add
                        >> a base class right away. If you cannot think of a specific
                        >> use case, there is little point in having a common base class.[/color]
                        >
                        >So, for example, you don't think it's worth including the base class as a
                        >way of indicating future intent?
                        >[/color]
                        If the intent is pretty sure of implementation, I guess it will save some
                        editing to include it at the start (unless you intended to define old-style classes
                        and factor the base class inheritance revisions into some global metaclass hack later
                        (not even really sure that's reliably possible, but pretty sure it would not be the
                        best style ;-) BTW 2.5 may let you mod classes by prefixing a decorator instead of
                        editing the first line. Not sure about the style/semantics tradeoffs there.

                        Regards,
                        Bengt Richter

                        Comment

                        • Steven Bethard

                          #13
                          Re: Stylistic question about inheritance

                          Andrew Koenig wrote:[color=blue]
                          > "Carl Banks" <invalidemail@a erojockey.com> wrote in message
                          > news:1112300127 .449931.146470@ o13g2000cwo.goo glegroups.com.. .
                          >[color=green]
                          >>Well, Python seems to get along fine without the ability to do
                          >>isinstance(fo o,file_like_obj ect); probably better off in the end for
                          >>it. So I'd say you should generally not do it. Inheritence is for
                          >>when different classes need to share functionality.[/color]
                          >
                          > That's really the question: Is it for when they need to share
                          > functionality, or when they are conceptually related in ways that might lead
                          > to shared functionality later?[/color]

                          I've typically only done the former. But I've definitely extracted
                          common ancestors later when I did find that two different classes should
                          share functionality.

                          STeVe

                          Comment

                          • Lonnie Princehouse

                            #14
                            Re: Stylistic question about inheritance

                            Well, that's true, but I meant to convey that no grammatical entity is
                            the base class of another entity, so it's a flat inheritance tree in
                            that respect. ASTNode would not be something that the parser would
                            know anything about.

                            I guess that's sort of moot if your expression trees are just a
                            contrived example; in that case, I'd say that how deep you want your
                            inheritance hierarchy to be depends entirely on how your program wants
                            to use it.

                            Comment

                            • Michele Simionato

                              #15
                              Re: Stylistic question about inheritance

                              Koenig:[color=blue]
                              > want to know about the Python community's stylistic
                              > preferences for defing
                              > such hierarchies that don't absolutely need a root.[/color]

                              I don't know if there is an official style guide or a Guido's
                              prononcement on the issue. Personally
                              I found such hierarchies attractive in the past, but
                              recently I realized that they look better on the paper
                              than in practice. A non-needed class just adds cognitive
                              burden to the maintainer. Also, I don't like to use
                              isinstance if I can avoid it. Finally, It is always easy to
                              refactor later and to add a base class
                              if there is a real need for it.
                              Paraphrasing Occam, I would say "don't multiply base classes without
                              necessity" ;)


                              Michele Simionato

                              Comment

                              Working...