Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Good or bad use of __repr__?

5 views
Skip to first unread message

Alaric Haag

unread,
Feb 3, 2009, 11:02:13 PM2/3/09
to pytho...@python.org
Hello,

Is the use of __repr__ below a "really bad idea"?

class Dimension():
def __init__(self, setp, name):
ptr = setp.contents.dim
while ptr.contents.name != name:
ptr = ptr.contents.next
self.name = ptr.contents.name
self.size = ptr.contents.size
self.unlimited = bool(ptr.contents.unlimited)
self.coord = ptr.contents.coord
def __repr__(self):
return '%g' % (self.size)

As written, if a program references a Dimension instance without an
attribute, it gets the size attrbute "by default". If it wants the other
attributes, they have to be spec'd. In the context of the code being
developed, the "size" attribute is the "logical" representation of the
dimension. I'm just wondering if this sort of design should be avoided.

Many thanks!

Alaric

Stephen Hansen

unread,
Feb 3, 2009, 11:23:40 PM2/3/09
to pytho...@python.org
>
> As written, if a program references a Dimension instance without an
> attribute, it gets the size attrbute "by default". If it wants the other
> attributes, they have to be spec'd. In the context of the code being
> developed, the "size" attribute is the "logical" representation of the
> dimension. I'm just wondering if this sort of design should be avoided.

Well the question is: does that repr give you sufficient information
to identify at least and possibly recreate that instance?

If you repr an int and it comes up as 50.. and repr a Dimension and it
comes up as 50, does that allow you to differentiate between them? If
you need to. I primarily use repr for a debugging tool, and in that
context I'd always for instances at least make it something like
<Dimension(size=50)> as the repr output. But I personally like to err
on the side of 'more is better' when it comes to repr output, and
would probably have put in the name/unlimited/coord even if they may
not always be present. So that if you're checking something after the
fact and all you have to go on is a repr of an object involved you
have more details to work with.

But there's no hard and fast rules. Generally, repr output should be
whatever you need to clearly reflect The Specific Object as a string.

--S

Steven D'Aprano

unread,
Feb 4, 2009, 12:18:29 AM2/4/09
to
On Tue, 03 Feb 2009 22:02:13 -0600, Alaric Haag wrote:

> Hello,
>
> Is the use of __repr__ below a "really bad idea"?
>
> class Dimension():
> def __init__(self, setp, name):
> ptr = setp.contents.dim
> while ptr.contents.name != name:
> ptr = ptr.contents.next
> self.name = ptr.contents.name
> self.size = ptr.contents.size
> self.unlimited = bool(ptr.contents.unlimited)
> self.coord = ptr.contents.coord
> def __repr__(self):
> return '%g' % (self.size)


As a rule of thumb, you should aim for:

eval( repr(obj) )

to recreate the obj. That's not always possible, but when possible, it is
an ideal to aspire to. Given that, I'd recommend:

def __repr__(self):
return '%s(%s, %s)' % (
self.__class__.__name__, self.ptr, self.name)
def __str__(self):
return "<dim=%g>" % self.size


except of course your class doesn't store ptr.


But looking at the code shown, I'm guessing you have bigger design
problems than just what __repr__ should look like. I suggest you read
this:

http://www.surfscranton.com/architecture/LawOfDemeter.htm


--
Steven

Steven D'Aprano

unread,
Feb 4, 2009, 12:29:01 AM2/4/09
to
On Wed, 04 Feb 2009 05:18:29 +0000, Steven D'Aprano wrote:

> ... I'd recommend:


>
> def __repr__(self):
> return '%s(%s, %s)' % (
> self.__class__.__name__, self.ptr, self.name)
> def __str__(self):
> return "<dim=%g>" % self.size
>
>
> except of course your class doesn't store ptr.

Ah crap, sorry, I meant setp not ptr. Sorry for the confusion.

--
Steven

Terry Reedy

unread,
Feb 4, 2009, 12:54:19 AM2/4/09
to pytho...@python.org
Alaric Haag wrote:
> Hello,
>
> Is the use of __repr__ below a "really bad idea"?
>
> class Dimension():
> def __init__(self, setp, name):
> ptr = setp.contents.dim
> while ptr.contents.name != name:
> ptr = ptr.contents.next
> self.name = ptr.contents.name
> self.size = ptr.contents.size
> self.unlimited = bool(ptr.contents.unlimited)
> self.coord = ptr.contents.coord
> def __repr__(self):
> return '%g' % (self.size)
>
> As written, if a program references a Dimension instance without an
> attribute, it gets the size attrbute "by default".

No it does not. It gets a string representation of the size. Not the
same thing.

Bruno Desthuilliers

unread,
Feb 4, 2009, 3:51:25 AM2/4/09
to
Alaric Haag a écrit :

> Hello,
>
> Is the use of __repr__ below a "really bad idea"?

I'd probably do the same as Stephen Hansen ("<Dimension(size=50)>") or
at least something quite similar.


Now on a totally unrelated point (micro optimization anyone ?):

> class Dimension():
> def __init__(self, setp, name):
> ptr = setp.contents.dim
> while ptr.contents.name != name:
> ptr = ptr.contents.next
> self.name = ptr.contents.name
> self.size = ptr.contents.size
> self.unlimited = bool(ptr.contents.unlimited)
> self.coord = ptr.contents.coord

In the above code, you're constantly refering to ptr.contents, and never
use ptr directly. Attribute lookup is not free, so it's better to avoid
them. Local bindings lookup, OTHO, is quite fast. IOW, this would better
be written as:

def __init__(self, setp, name):
contents = setp.contents.dim
while contents.name != name:
contents = contents.next
self.name = contents.name
self.size = contents.size
self.unlimited = bool(contents.unlimited)
self.coord = contents.coord

0 new messages