Dealing with the __str__ method in classes with lots of attributes

Ethan Furman ethan at stoneleaf.us
Sat May 12 09:10:13 EDT 2012


Karl Knechtel wrote:
> On Thu, May 10, 2012 at 9:33 AM, Andreas Tawn <andreas.tawn at ubisoft.com> wrote:
>> And there's also something like...
>>
>> return "\n".join((": ".join((str(k), str(self.__dict__[k]))) for k in self.__dict__))
>>
>> which is a nice length, but I lose control of the order of the attributes and the formatting is fixed. It also looks a bit too much like Lisp ;o)
>>
>> Is there a better way?
> 
> If you don't care about being able to change the attributes
> dynamically, define the `__slots__` of your class  [...]

Firstly, __slots__ is a tuple.

Secondly, this is bad advice.  __slots__ is there as a memory 
optimization for classes that will have thousands of instances and do 
not need the ability to have arbitrary attributes added after creation. 
  __slots__ is an advanced feature, and as such is easier to get wrong. 
  It is *not* there to make __str__ nor __repr__ easier to write.

8<-----------------------------------------------------------------------
Python 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit 
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
 >>> class Test1(object):
...     __slots__ = ('item', 'size')
...     desc = 'class-only attribute'
...

 >>> t1 = Test1()
 >>> t1.desc = 'read-only attribute'      # fails because 'desc' is
                                          # not in __slots__
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
AttributeError: 'Test1' object attribute 'desc' is read-only

 >>> print t1.item                        # fails because 'item' was
                                          # not set
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
AttributeError: item

 >>> class Test2(Test1):
...     def __init__(self, price):
...         self.price = price
...
 >>> t2 = Test2(7.99)          # __slots__ not defined in
                               # subclass, optimizations lost

 >>> t2.oops = '__slots__ no longer active'
 >>> print t2.oops
__slots__ no longer active
8<-----------------------------------------------------------------------

~Ethan~



More information about the Python-list mailing list