how to use __str__ and __repr__?

J

Jim Newton

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__'
 
J

Jim Newton

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 said:
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.

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__'
 
J

Jim Newton

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
 
P

Peter Hansen

Jim said:
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?
 
L

Larry Bates

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 said:
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__'
 
E

Erik Max Francis

Jim said:
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?
 
P

Peter Hansen

Jim said:
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
 
J

Jim Newton

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.
 
J

Jim Newton

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
 
C

Carl Banks

Jim said:
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())
 
E

Erik Max Francis

Jim said:
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.

Because __str__ is a special method which str defers to. If you want
the str of anObject, call str(anObject). The object will then show you
the string representation for that object. You shouldn't care whether
or not it's got that behavior from defining a __str__ method, or whether
it's gotten it from a parent class.
 
J

Jim Newton

wow that works...

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

thanks
-jim
 
J

Jim Newton

wow that is great.

now the other question:

class Pair(list):
...

how can i "cast", "promote" [] to class Pair?
 
P

Peter Maas

Erik said:
Jim Newton wrote: [...]
class Pair(list):
...

how can i "cast", "promote" [] to class Pair?


You can't.

Perhaps I've got it wrong but Jim probably asks for overwriting
the __getitem__ method.

Mit freundlichen Gruessen,

Peter Maas
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,049
Latest member
Allen00Reed

Latest Threads

Top