[Dev] Those annoying __str__ methods

Phillip J. Eby pje at telecommunity.com
Tue Jan 18 13:53:50 PST 2005


At 01:27 PM 1/18/05 -0800, Donn Denman wrote:
>You mentioned how often you curse those __str__ methods, on items like 
>EmailAddress, and I've been thinking maybe we should move them.  You hate 
>is that they are hooked in to str(), so you end up calling them by 
>accident, often when debugging as I recall.  What I like is that there's a 
>known way to convert things to a nice user-readable representation.  The 
>Chandler convention of using the "displayName" attribute doesn't seem to 
>work well in some cases, because you may need a method to decide how to 
>display.  You probably want a method for ref collections, and even things 
>like EmailAddress have a couple different ways that they display based on 
>whether or not a fullName attribute is present.  So I figured __str__ was 
>the standard way to do this when a method is needed.   But there's no 
>reason we need to use __str__.  Maybe we should use a display() method 
>instead of __str__, and both of us will be happy?
>
>We don't actually have very many __str__ methods yet, so it wouldn't be 
>too hard to make a change like this.  It would be great if ref collections 
>knew how to display themselves as a nice comma-separated list of displayed 
>items.  Most items would inherit a default display() method that just uses 
>the displayName attribute.
>
>What do you think?  Should we move the __str__ methods?  Is there some 
>other standard that we should be adopting?  Let me know if you think this 
>is a good idea, and I'll try to work with you on this.

The thing about __str__ and __repr__ is that they should never ever *ever* 
raise an uncaught error, if you want to be able to debug them.  In the case 
of persistent objects like in Chandler, this means that if __str__ or 
__repr__ use item attributes, they must be able to handle any errors that 
result from accessing that item.  One way to do this would be to have a 
default __str__ and __repr__ methods in a content item base class that look 
like this:

     def __str__(self):
         try:
             return self.displayName
         except:
             # fallback to simple known-failsafe rendering
             # possibly incorporating error info

For classes that need a method to compute 'displayName', just use a 
'property'; if it breaks you'll still get the default representation and 
you'll know right away your property is broken.

Also, the above code isn't perfect, as it will eat errors like 
KeyboardInterrupt.  In general, having bare 'except' statements is a bad 
idea unless you're going to log the exception in some way, but for __str__ 
that cure would be worse than the disease.  :)



More information about the Dev mailing list