why i love python...

Quinn Dunkan quinn at hurl.ugcs.caltech.edu
Mon Feb 11 18:05:07 EST 2002


On Wed, 6 Feb 2002 17:34:52 -0800, Mark McEahern <mark at mceahern.com> wrote:
>python comes with a slew of special methods for objects that you can
>leverage to do some really neat things.  consider __str__, which is called
>on your objects when you <b>print</b> them.  if you don't define __str__,
>that's ok, you'll get something like this:

Of course, just about every object oriented language has this, from haskell's
'show' to CLOS's 'print-object' to eiffel's 'out', so python doesn't have
a monopoly :)

>obviously, i should return something more meaningful than that.  for
>instance, it might be nice to return an xml representation of the object.
>again, with python this is unbelievably easy:

I'd assert that this is a misuse of __str__.  __str__ is supposed to be
something all objects use to present human readable output.  I would only use
it to make XML if a) I was prepared to make *all* objects' __str__s return XML
(already too late for that :) and b) I thought XML was human-readable (way too
late for that).

I'd go with a 'to_xml()'.  __str__ is just overloading the built in function
str().  There's nothing special about it except that the REPL invokes it
automatically.  You wouldn't overload '+' to print strings, would you (sather
notwithstanding)?  Or, you wouldn't overload bit-shift to... err... pay
no attention to those other languages.

>this snippet shows:
>
><ul>
>  <li>how you can use self.__dict__ to access an object's attributes.</li>
>  <li>how you can iterate over the keys of a dictionary (i believe that's
>new with python 2.2).</li>
>  <li>how you can use self.__class__ to access an instance's class; and
>__class__.__name__ to access the name of the class as a string.</li>
></ul>

Yep, python's introspection is nice.

>i think this shows some of the power of python.  particularly, how special
>methods can save you an amazing amount of time.  to me, the natural next

There's nothing special about most __special__ methods except some simple
syntax transformation (str(o) -> o.__str__()).  And if you overload a widely
used, general purpose method to do something different from its usual meaning
you might spend an amazing amount of time debugging why some objects aren't
getting XML-ified properly (they're actually the wrong type, but that's hidden
by the fact that they already have a working __str__ method).

><ul>
>  <li>handle list attributes intelligently.</li>
>  <li>determine whether attributes are themselves subclasses of PrintsXml,
>in which case you can just let them print themselves rather than wrapping
>them in xml tags manually.</li>

A more pythonic way to do the second would be:

for elt in stuff_to_xmlify:
    try:
        return elt.to_xml()
    except AttributeError:
        fallback general-purpose xmlification

>of course, i haven't even touched on the most exciting aspect of all this:
>__repr__.  __repr__ allows me to return a string representation of my object
>that can be used to re-create it.  what i don't know is how that compares to
>pickling, but i'm sure the latter is tastier.  ;-)

I hope this doesn't excite you unduly, but it's not just __repr__: *any*
method allows you to return a string representation of your object! :)
That is, if your object can be recreated from a string, which most can't
easily, and those that can do so inefficiently.

The relationship with pickle is that __repr__ traditionally (but actually
usually doesn't) flattens your object to a string which should be short,
printable, and reconstitutable by the python parser (the first one often
contradicts the other two, hence pickle), while pickle flattens your object to
a string which can be really long, not necessarily printable (containing
binary) and is reconstitutable only by the unpickler.

repr() usually *doesn't* flatten to a string, actually, so the distinction
between __str__ and __repr__ is sort of vague.  The exception is for simple
built-in types, like ints, floats, strings, lists, etc., where the difference
may be subtle but is important (compare str('hello\nthere') with
repr('hello\nthere')).

If the python developers had gotten really anal about repr() doing what it's
purpose supposedly is, then repr(function) would print the text of the
function.  And then if the compiler used repr() instead of marshal() to
save compiled modules to disk, .pyc files would be the same as the .py files
they were supposedly compiled from :)

and-what-fun-that-would-be-ly y'rs



More information about the Python-list mailing list