FAQ
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?

Search Discussions

  • Carl Banks at Mar 31, 2005 at 8:15 pm
    Andrew Koenig wrote:
    [snip]
    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?
    Well, Python seems to get along fine without the ability to do
    isinstance(foo,file_like_object); 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
  • Andrew Koenig at Mar 31, 2005 at 8:23 pm
    "Carl Banks" <invalidemail at aerojockey.com> wrote in message
    news:1112300127.449931.146470 at o13g2000cwo.googlegroups.com...
    Well, Python seems to get along fine without the ability to do
    isinstance(foo,file_like_object); 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.
    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?
  • Donn Cave at Mar 31, 2005 at 8:55 pm
    In article
    <P_Y2e.493283$w62.145022 at bgtnsc05-news.ops.worldnet.att.net>,
    "Andrew Koenig" wrote:
    "Carl Banks" <invalidemail at aerojockey.com> wrote in message
    news:1112300127.449931.146470 at o13g2000cwo.googlegroups.com...
    Well, Python seems to get along fine without the ability to do
    isinstance(foo,file_like_object); 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.
    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?
    No -- inheritance is for implementation, not to express conceptual
    relationship.

    Donn Cave, donn at u.washington.edu
  • Steven Bethard at Mar 31, 2005 at 9:20 pm

    Andrew Koenig wrote:
    "Carl Banks" <invalidemail at aerojockey.com> wrote in message
    news:1112300127.449931.146470 at o13g2000cwo.googlegroups.com...
    Well, Python seems to get along fine without the ability to do
    isinstance(foo,file_like_object); 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.
    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?
    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
  • Martin v. Löwis at Mar 31, 2005 at 8:18 pm

    Andrew Koenig wrote:
    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?
    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
  • Andrew Koenig at Mar 31, 2005 at 8:24 pm
    ""Martin v. L?wis"" <martin at v.loewis.de> wrote in message
    news:424C5B09.9090006 at v.loewis.de...
    You would normally try to avoid type queries, and rely on virtual
    methods instead, if possible.
    Of course.
    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. Indeed.
    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.
    So, for example, you don't think it's worth including the base class as a
    way of indicating future intent?
  • Martin v. Löwis at Mar 31, 2005 at 9:11 pm

    Andrew Koenig wrote:
    So, for example, you don't think it's worth including the base class as a
    way of indicating future intent?
    No. In this respect, I believe in XP: refactor when the need comes up,
    but not before.

    Regards,
    Martin
  • Bengt Richter at Mar 31, 2005 at 9:24 pm

    On Thu, 31 Mar 2005 20:24:08 GMT, "Andrew Koenig" wrote:
    ""Martin v. L?wis"" <martin at v.loewis.de> wrote in message
    news:424C5B09.9090006 at v.loewis.de...
    You would normally try to avoid type queries, and rely on virtual
    methods instead, if possible.
    Of course.
    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. Indeed.
    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.
    So, for example, you don't think it's worth including the base class as a
    way of indicating future intent?
    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
  • Steve Holden at Apr 1, 2005 at 6:59 am

    Andrew Koenig wrote:
    ""Martin v. L?wis"" <martin at v.loewis.de> wrote in message
    news:424C5B09.9090006 at v.loewis.de...

    You would normally try to avoid type queries, and rely on virtual
    methods instead, if possible.

    Of course.

    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.

    Indeed.

    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.

    So, for example, you don't think it's worth including the base class as a
    way of indicating future intent?
    The obvious XP response to the question is "You aren't going to need
    it". If you already have the intent then basically you appear to be
    saying "I *am* going to need it".

    Since you say that almost as an integral feature of the specification
    I'm not sure I understand why you asked the question in the first place
    - unless it's really an anthropological inquiry.

    regards
    Steve
    --
    Steve Holden +1 703 861 4237 +1 800 494 3119
    Holden Web LLC http://www.holdenweb.com/
    Python Web Programming http://pydish.holdenweb.com/
  • Lonnie Princehouse at Mar 31, 2005 at 8:22 pm
    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(ASTNode): ...
    class BinaryExpr(ASTNode): ...

    or you could dynamically generate classes with inheritance based on a
    grammar definition
  • Andrew Koenig at Mar 31, 2005 at 8:28 pm
    "Lonnie Princehouse" <finite.automaton at gmail.com> wrote in message
    news:1112300578.456411.274110 at f14g2000cwb.googlegroups.com...
    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...
    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.
    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(ASTNode): ...
    class BinaryExpr(ASTNode): ...
    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.
  • Irmen de Jong at Mar 31, 2005 at 8:40 pm

    Andrew Koenig wrote:
    "Lonnie Princehouse" <finite.automaton at gmail.com> wrote in message
    news:1112300578.456411.274110 at f14g2000cwb.googlegroups.com...

    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...

    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.
    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
  • Lonnie Princehouse at Mar 31, 2005 at 10:20 pm
    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.
  • Michele Simionato at Apr 1, 2005 at 3:36 am

    Koenig:
    want to know about the Python community's stylistic
    preferences for defing
    such hierarchies that don't absolutely need a root.
    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
  • Ivan Van Laningham at Apr 1, 2005 at 4:25 am
    Hi All--

    Michele Simionato wrote:
    recently I realized that they look better on the paper
    than in practice. A non-needed class just adds cognitive
    burden to the maintainer.
    Agreed. Too many classes make me think I'm back trying to figure out
    what the )(*#@$ those guys were thinking making 200 twelve-line ASP
    classes. Ya think there's a hard-wired limit past which your brain
    melts?
    Paraphrasing Occam, I would say "don't multiply base classes without
    necessity" ;)
    +1 QOTW

    Metta,
    Ivan
    ----------------------------------------------
    Ivan Van Laningham
    God N Locomotive Works
    http://www.andi-holmes.com/
    http://www.foretec.com/python/workshops/1998-11/proceedings.html
    Army Signal Corps: Cu Chi, Class of '70
    Author: Teach Yourself Python in 24 Hours
  • Guy Bolton King at Apr 1, 2005 at 12:49 pm

    "Andrew Koenig" <ark at acm.org> writes:

    "Lonnie Princehouse" <finite.automaton at gmail.com> wrote in message
    news:1112300578.456411.274110 at f14g2000cwb.googlegroups.com...
    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...
    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.
    Oddly enough, I've just been pondering the same question (albeit for
    Perl, but the same reasoning applies). The only cases I've found
    useful thus far are:

    - implementation inheritance (in the case of default methods in a
    callback interface class):

    class CallbackInterface:

    def handleEvent(self, event):
    """Handle an event"""
    pass

    def handleSignal(self, signal):
    """Handle a signal"""
    pass

    This also helps to document what's expected of callback classes,
    even though they don't _have_ to inherit CallbackInterface
    (enforcing this through isinstance() in the calling class would be
    rude).

    - hierarchies of exception classes (allowing one to catch general
    classes of exceptions, since except implicitly uses isinstance(),
    rather than a specific class). Of course, Python already has a
    hierarchy of exceptions. I had to implement my own for Perl.
    looks like interfaces _may_ be added to Python 3.0, but they sound
    more like (IIRC) ML's signatures and C++'s Standard Library
    requirements i.e. a requirement that the class implements certain
    functions, rather than a requirement to inherit from a particular base
    class.

    Guy.
  • Stefan Seefeld at Mar 31, 2005 at 8:49 pm

    Andrew Koenig wrote:

    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?
    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




    From bogus@does.not.exist.com Thu Mar 31 23:15:01 2005
    From: bogus@does.not.exist.com ()
    Date: Thu, 31 Mar 2005 21:15:01 -0000
    Subject: (no subject)
    Message-ID: <mailman.1448.1163321507.2969.python-list@python.org>

    #! rnews 1765
    Newsgroups: comp.lang.python
    Path: news.xs4all.nl!newsspool.news.xs4all.nl!transit.news.xs4all.nl!195.241.76.212.MISMATCH!transit1.news.tiscali.nl!tiscali!transit0.news.tiscali.nl!tudelft.nl!130.161.131.117.MISMATCH!tudelft.nl!newsfeed.multikabel.nl!gatel-ffm!gatel-ffm!proxad.net!proxad.net!newsread.com!news-xfer.newsread.com!nntp.abs.net!attws2!ip.att.net!NetNews1!xyzzy!nntp
    From: Harry George <harry.g.george at boeing.com>
    Subject: Re: Generating RTF with Python
    X-Nntp-Posting-Host: cola2.ca.boeing.com
    Content-Type: text/plain; charset=us-ascii
    Message-ID: <xqxd5tfo7p1.fsf at cola2.ca.boeing.com>
    User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3
    Lines: 37
    Sender: hgg9140 at cola2.ca.boeing.com
    Organization: The Boeing Company
    References: <mailman.1137.1112277702.1799.python-list at python.org> <slrnd4o7hd.h5k.axel at m2.sine>
    Mime-Version: 1.0
    Date: Thu, 31 Mar 2005 20:56:42 GMT
    Xref: news.xs4all.nl comp.lang.python:370154

    Axel Straschil <axel at straschil.com> writes:
    Hello!
    does anyone know of a high-level solution to produce RTF from Python
    (something similar to
    Reportlab for producing PDF)?
    Spend hours of googeling and searching, also in this NG, about two
    months ago. My conclusion is: On windwos, maybe you can include some
    hacks with dll's, under linux, linux support for generating rtf is none,
    and so is python's.

    My workaround was:
    http://www.research.att.com/sw/download/
    This includes an html2rtf converter, which I access from python via
    popen and temporary files. Not high-level, not very sexy ... ;-(

    Lg,
    AXEL.
    --
    "Aber naja, ich bin eher der Forentyp." Wolfibolfi's outing in
    http://www.informatik-forum.at/showpost.php?p 6342&postcount
    I generate docbook and convert that to rtf. I generate the docbook
    from my pdx markup:

    http://www.seanet.com/~hgg9140/comp/index.html#L007

    If you go this route, your python code is actually writing pdx, and
    you need a 2 step conversion (pdx2docbook.py, then openjade for the
    xml-to-rtf step).

    --
    harry.g.george at boeing.com
    6-6M21 BCA CompArch Design Engineering
    Phone: (425) 294-4718

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedMar 31, '05 at 7:33p
activeApr 1, '05 at 12:49p
posts18
users13
websitepython.org

People

Translate

site design / logo © 2022 Grokbase