Velocity Reviews > how to use __str__ and __repr__?

# how to use __str__ and __repr__?

Jim Newton
Guest
Posts: n/a

 06-07-2004
hi all, does anyone know what print does if there is no __str__ method?
i'm trying ot override the __repr__. If anyone can give me some advice
it would be great to have.

I have defined a lisp-like linked list class as a subclass of list.
The __iter__ seems to work as i'd like, by traversing the links,
and the __repr__ seems to work properly for somethings but not others.

The basic idea is that a list such as [ 1, 2, 3, 4] is converted to
[1, [2, [3, [4, nil]]], thus allowing me to push (cons) a new element
non-destructively onto the beginning of the list; e.g.

x = seq2pair( [ 3,4,5]) --> [ 3, [4, [5, nil]]]
y = x.cons(2) --> [ 2, [3, [4, [5, nil]]]
z = y.cons(1) --> [ 1, [ 2, [3, [4, [5, nil]]]]

for elt in z: # iterates elt=1, elt=2, elt=3 ...
pass

I would love to know how to define the __repr__ or __str__
method so that it is able to print everything the way print
normally works, except that instances of my class gets printed
special. I want to print [ 1, [ 2, [3, [4, [5, nil]]]]
simple as a space seperated list. It works most of the time.
--> ( 1 2 3 4 5)

Another question is whether there is a way to promote an
empty list [] to an instance of Pair?

class Pair(list):

def __iter__(self):
while self:
yield self.car()
self = self.cdr()

def __repr__(self):
middle = " ".join( [ substr.__str__() for substr in self])
return "( " + middle + " )"

# x = (cons x l_y)
# ==> x = l_y.cons(x)
def cons(self, car):
new = Pair()
new.append(car)
new.append(self)
return new

def car(self):
if self:
return self[0]
return nil

def cdr(self):
if len(self)<2:
return nil
return self[1]

nil = Pair()

# [ 1, 2, 3] --> [1, [2, [3, nil]]]
def seq2pair(seq):
new = Pair()
for index in xrange( len(seq), 0, -1):
new = new.cons(seq[index - 1])
return new

mylist = seq2pair( [1,2,3,4,5])
print mylist # correctly prints --> ( 1 2 3 4 5)

mylist2 = seq2pair( [11.1, 21.1, 31.1, 41.1, mylist])
print mylist2
# correctly prints --> ( 11.1 21.1 31.1 41.1 ( 1 2 3 4 5 ) )

class another:
pass

print another() # prints --> <__main__.another instance at 0x8132b64>

# ????????????????????????????????????????
print seq2pair( [ another(), another() ]) # FAILS
# ????????????????????????????????????????

Traceback (most recent call last):
File "xyz.py", line 52, in ?
print seq2pair( [ another(), another() ])
File "xyz.py", line 13, in __repr__
return "( " + " ".join( [ substr.__str__() for substr in self]) + " )"
AttributeError: another instance has no attribute '__str__'

Jim Newton
Guest
Posts: n/a

 06-07-2004
thanks for responding,
i was expecting class().__str__()
to evaluate to the string "<__main__.another instance at 0x8132b64>"
because that what print does with class().
but alas it does not.

why does print class() not give me the same error as class().__str__()?
that's what i do not understand.

-jim

Larry Bates wrote:
> I don't understand what you are trying to do, but
> the problem is that when you define class 'another'
> the following line doesn't make sense:
>
> middle = " ".join( [ substr.__str__() for substr in self])
>
> The instance of another doesn't have a __str__ method
> defined (e.g. it's an empty class). All of your other
> tests have a class that does have a __str__ method
> because it was inherited from the baseclass list.
>
> You could try:
>
> class another(list):
> pass
>
> Larry Bates
> Syscon, Inc.
>
> "Jim Newton" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
>
>>hi all, does anyone know what print does if there is no __str__ method?
>>i'm trying ot override the __repr__. If anyone can give me some advice
>>it would be great to have.
>>
>>I have defined a lisp-like linked list class as a subclass of list.
>>The __iter__ seems to work as i'd like, by traversing the links,
>>and the __repr__ seems to work properly for somethings but not others.
>>
>>The basic idea is that a list such as [ 1, 2, 3, 4] is converted to
>>[1, [2, [3, [4, nil]]], thus allowing me to push (cons) a new element
>>non-destructively onto the beginning of the list; e.g.
>>
>>x = seq2pair( [ 3,4,5]) --> [ 3, [4, [5, nil]]]
>>y = x.cons(2) --> [ 2, [3, [4, [5, nil]]]
>>z = y.cons(1) --> [ 1, [ 2, [3, [4, [5, nil]]]]
>>
>>for elt in z: # iterates elt=1, elt=2, elt=3 ...
>> pass
>>
>>I would love to know how to define the __repr__ or __str__
>>method so that it is able to print everything the way print
>>normally works, except that instances of my class gets printed
>>special. I want to print [ 1, [ 2, [3, [4, [5, nil]]]]
>>simple as a space seperated list. It works most of the time.
>>--> ( 1 2 3 4 5)
>>
>>Another question is whether there is a way to promote an
>>empty list [] to an instance of Pair?
>>
>>class Pair(list):
>>
>> def __iter__(self):
>> while self:
>> yield self.car()
>> self = self.cdr()
>>
>> def __repr__(self):
>> middle = " ".join( [ substr.__str__() for substr in self])
>> return "( " + middle + " )"
>>
>> # x = (cons x l_y)
>> # ==> x = l_y.cons(x)
>> def cons(self, car):
>> new = Pair()
>> new.append(car)
>> new.append(self)
>> return new
>>
>> def car(self):
>> if self:
>> return self[0]
>> return nil
>>
>> def cdr(self):
>> if len(self)<2:
>> return nil
>> return self[1]
>>
>>nil = Pair()
>>
>>
>># [ 1, 2, 3] --> [1, [2, [3, nil]]]
>>def seq2pair(seq):
>> new = Pair()
>> for index in xrange( len(seq), 0, -1):
>> new = new.cons(seq[index - 1])
>> return new
>>
>>mylist = seq2pair( [1,2,3,4,5])
>>print mylist # correctly prints --> ( 1 2 3 4 5)
>>
>>
>>mylist2 = seq2pair( [11.1, 21.1, 31.1, 41.1, mylist])
>>print mylist2
>># correctly prints --> ( 11.1 21.1 31.1 41.1 ( 1 2 3 4 5 ) )
>>
>>class another:
>> pass
>>
>>print another() # prints --> <__main__.another instance at 0x8132b64>
>>
>># ????????????????????????????????????????
>>print seq2pair( [ another(), another() ]) # FAILS
>># ????????????????????????????????????????
>>
>>Traceback (most recent call last):
>> File "xyz.py", line 52, in ?
>> print seq2pair( [ another(), another() ])
>> File "xyz.py", line 13, in __repr__
>> return "( " + " ".join( [ substr.__str__() for substr in self]) +

>
> " )"
>
>>AttributeError: another instance has no attribute '__str__'
>>

>
>
>

Jim Newton
Guest
Posts: n/a

 06-07-2004
i read that in the documenation. and i assumed from that that
print another()
actually prints the string returned from another().__str__()
and thus __str__ must be being inherited from the superclass
of another, but apparently print does something different.

why does print another() actually print something rather than
complaining that there is no __str__ defined?

-jim

Peter Hansen wrote:
> Jim Newton wrote:
>
>> hi all, does anyone know what print does if there is no __str__ method?

>
>
> From the documentation at http://docs.python.org/ref/customization.html :
>
> __repr__( self)
>
> Called by the repr() built-in function and by string conversions
> (reverse quotes) to compute the ``official'' string representation of an
> object. .... If a class defines __repr__() but not __str__(), then
> __repr__() is also used when an ``informal'' string representation of
> instances of that class is required.
>
> Does that help?

Peter Hansen
Guest
Posts: n/a

 06-07-2004
Jim Newton wrote:

> hi all, does anyone know what print does if there is no __str__ method?

From the documentation at http://docs.python.org/ref/customization.html :

__repr__( self)

Called by the repr() built-in function and by string conversions
(reverse quotes) to compute the ``official'' string representation of an
object. .... If a class defines __repr__() but not __str__(), then
__repr__() is also used when an ``informal'' string representation of
instances of that class is required.

Does that help?

Larry Bates
Guest
Posts: n/a

 06-07-2004
I don't understand what you are trying to do, but
the problem is that when you define class 'another'
the following line doesn't make sense:

middle = " ".join( [ substr.__str__() for substr in self])

The instance of another doesn't have a __str__ method
defined (e.g. it's an empty class). All of your other
tests have a class that does have a __str__ method
because it was inherited from the baseclass list.

You could try:

class another(list):
pass

Larry Bates
Syscon, Inc.

"Jim Newton" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> hi all, does anyone know what print does if there is no __str__ method?
> i'm trying ot override the __repr__. If anyone can give me some advice
> it would be great to have.
>
> I have defined a lisp-like linked list class as a subclass of list.
> The __iter__ seems to work as i'd like, by traversing the links,
> and the __repr__ seems to work properly for somethings but not others.
>
> The basic idea is that a list such as [ 1, 2, 3, 4] is converted to
> [1, [2, [3, [4, nil]]], thus allowing me to push (cons) a new element
> non-destructively onto the beginning of the list; e.g.
>
> x = seq2pair( [ 3,4,5]) --> [ 3, [4, [5, nil]]]
> y = x.cons(2) --> [ 2, [3, [4, [5, nil]]]
> z = y.cons(1) --> [ 1, [ 2, [3, [4, [5, nil]]]]
>
> for elt in z: # iterates elt=1, elt=2, elt=3 ...
> pass
>
> I would love to know how to define the __repr__ or __str__
> method so that it is able to print everything the way print
> normally works, except that instances of my class gets printed
> special. I want to print [ 1, [ 2, [3, [4, [5, nil]]]]
> simple as a space seperated list. It works most of the time.
> --> ( 1 2 3 4 5)
>
> Another question is whether there is a way to promote an
> empty list [] to an instance of Pair?
>
> class Pair(list):
>
> def __iter__(self):
> while self:
> yield self.car()
> self = self.cdr()
>
> def __repr__(self):
> middle = " ".join( [ substr.__str__() for substr in self])
> return "( " + middle + " )"
>
> # x = (cons x l_y)
> # ==> x = l_y.cons(x)
> def cons(self, car):
> new = Pair()
> new.append(car)
> new.append(self)
> return new
>
> def car(self):
> if self:
> return self[0]
> return nil
>
> def cdr(self):
> if len(self)<2:
> return nil
> return self[1]
>
> nil = Pair()
>
>
> # [ 1, 2, 3] --> [1, [2, [3, nil]]]
> def seq2pair(seq):
> new = Pair()
> for index in xrange( len(seq), 0, -1):
> new = new.cons(seq[index - 1])
> return new
>
> mylist = seq2pair( [1,2,3,4,5])
> print mylist # correctly prints --> ( 1 2 3 4 5)
>
>
> mylist2 = seq2pair( [11.1, 21.1, 31.1, 41.1, mylist])
> print mylist2
> # correctly prints --> ( 11.1 21.1 31.1 41.1 ( 1 2 3 4 5 ) )
>
> class another:
> pass
>
> print another() # prints --> <__main__.another instance at 0x8132b64>
>
> # ????????????????????????????????????????
> print seq2pair( [ another(), another() ]) # FAILS
> # ????????????????????????????????????????
>
> Traceback (most recent call last):
> File "xyz.py", line 52, in ?
> print seq2pair( [ another(), another() ])
> File "xyz.py", line 13, in __repr__
> return "( " + " ".join( [ substr.__str__() for substr in self]) +

" )"
> AttributeError: another instance has no attribute '__str__'
>

Erik Max Francis
Guest
Posts: n/a

 06-07-2004
Jim Newton wrote:

> thanks for responding,
> i was expecting class().__str__()
> to evaluate to the string "<__main__.another instance at 0x8132b64>"
> because that what print does with class().
> but alas it does not.
>
> why does print class() not give me the same error as
> class().__str__()?
> that's what i do not understand.

In the example you gave, your class is derived from list, so it uses
list.__str__. It's doing exactly what an object-oriented system should
do; defer to the base class. Why do you think that's wrong?

--
__ Erik Max Francis && http://www.velocityreviews.com/forums/(E-Mail Removed) && http://www.alcyone.com/max/
/ \ San Jose, CA, USA && 37 20 N 121 53 W && AIM erikmaxfrancis
\__/ Whoever contends with the great sheds his own blood.
-- Sa'di

Peter Hansen
Guest
Posts: n/a

 06-08-2004
Jim Newton wrote:

> i read that in the documenation. and i assumed from that that
> print another()
> actually prints the string returned from another().__str__()
> and thus __str__ must be being inherited from the superclass
> of another, but apparently print does something different.
>
> why does print another() actually print something rather than
> complaining that there is no __str__ defined?

I believe print basically calls str(obj) on the object, and
str() is a builtin which (I believe) basically tries to call
__str__() and if that is not defined, calls __repr__(). If
__repr__ is not defined, it probably defers to a standard
representation based on the id() of the object, which is
always defined.

Not sure what else you're trying to do (I haven't read your
full post) but I believe this and some thought should answer
for pretty much everything you're seeing.

Note that you should probably never call __str__() directly,
but call the str() builtin instead. Same for __repr__()
versus the repr() builtin.

-Peter

Jim Newton
Guest
Posts: n/a

 06-08-2004
if that is the case then why does the following fail

class another:
pass

another.__str__()

I would think that would return a string such as
"<__main__.another instance at 0x8132b64>"
but it does not seem to.

Erik Max Francis wrote:
> Jim Newton wrote:
>
>
>>thanks for responding,
>>i was expecting class().__str__()
>>to evaluate to the string "<__main__.another instance at 0x8132b64>"
>>because that what print does with class().
>>but alas it does not.
>>
>>why does print class() not give me the same error as
>>class().__str__()?
>>that's what i do not understand.

>
>
> In the example you gave, your class is derived from list, so it uses
> list.__str__. It's doing exactly what an object-oriented system should
> do; defer to the base class. Why do you think that's wrong?
>

Jim Newton
Guest
Posts: n/a

 06-08-2004
hmm, even when i change it to calling str() rather than __str__()
it does not work.

class another:
pass

print another() # works
another().str() # does not work

does anyone know why?

-jim

Peter Hansen wrote:
> Jim Newton wrote:
>
>> i read that in the documenation. and i assumed from that that
>> print another()
>> actually prints the string returned from another().__str__()
>> and thus __str__ must be being inherited from the superclass
>> of another, but apparently print does something different.
>>
>> why does print another() actually print something rather than
>> complaining that there is no __str__ defined?

>
>
> I believe print basically calls str(obj) on the object, and
> str() is a builtin which (I believe) basically tries to call
> __str__() and if that is not defined, calls __repr__(). If
> __repr__ is not defined, it probably defers to a standard
> representation based on the id() of the object, which is
> always defined.
>
> Not sure what else you're trying to do (I haven't read your
> full post) but I believe this and some thought should answer
> for pretty much everything you're seeing.
>
> Note that you should probably never call __str__() directly,
> but call the str() builtin instead. Same for __repr__()
> versus the repr() builtin.
>
> -Peter

Carl Banks
Guest
Posts: n/a

 06-08-2004
Jim Newton wrote:
> hmm, even when i change it to calling str() rather than __str__()
> it does not work.
>
> class another:
> pass
>
> print another() # works
> another().str() # does not work
>
> does anyone know why?

str is a function, not a method.

str(another())

--
CARL BANKS http://www.aerojockey.com/software
"If you believe in yourself, drink your school, stay on drugs, and
don't do milk, you can get work."
-- Parody of Mr. T from a Robert Smigel Cartoon