str() for containers

G

George Sakkis

Hi all,

I find the string representation behaviour of builtin containers
(tuples,lists,dicts) unintuitive in that they don't call recursively str()
on their contents (e.g. as in Java) :

###########################################
class A(object):
def __str__(self): return "a"
print A() a
print [A()]
[ said:
print map(str,[A()])
['a']

###########################################

It's even more cumbersome for containers of containers (e.g. lists of dicts,
etc.). Of course one can (or should) encapsulate such stuctures in a class
and define __str__ to behave as expected, but why not having it by default ?
Is there a good reason for this ?

George
 
D

Donn Cave

"George Sakkis said:
I find the string representation behaviour of builtin containers
(tuples,lists,dicts) unintuitive in that they don't call recursively str()
on their contents (e.g. as in Java)

Please find last week's answers to this question at
http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&th=62e7a6469ac7b40b

If you're still interested in further discussion of this
point, you could present an account of Java's approach
for the edification of those of us who don't know.

Donn Cave, (e-mail address removed)
 
D

Dan Bishop

Donn Cave said:
Please find last week's answers to this question at
http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&th=62e7a6469ac7b40b

If you're still interested in further discussion of this
point, you could present an account of Java's approach
for the edification of those of us who don't know.

All Java classes include a toString() method (defined in the root
class java.lang.Object), which returns the string representation of
that object. Each of the standard collection classes in java.util
defines its toString() method to recursively call toString() on its
elements.

For example, the program

import java.util.*;
public class Foo {
public static void main(String[] args) {
List lst = new ArrayList();
lst.add("a");
lst.add("b");
lst.add("c");
System.out.println(lst);
}
}

prints "[a, b, c]".

(Btw, this reminds me of something I like about Python: There are
literals for variable length arrays, so you don't have to write code
like that.)

The difference from Python's approach is that there isn't an
equivalent to Python's str/repr distinction. Obviously, when there's
only one string conversion method, you won't use the wrong one.

The other difference is that the built-in array types don't have a
meaningful toString() method, so

public class Foo {
public static void main(String[] args) {
String[] arr = {"a", "b", "c"};
System.out.println(arr);
}
}

prints "[Ljava.lang.String;@df6ccd" (or something similar).
 
D

Dan Bishop

Donn Cave said:
Please find last week's answers to this question at
http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&th=62e7a6469ac7b40b

If you're still interested in further discussion of this
point, you could present an account of Java's approach
for the edification of those of us who don't know.

All Java classes include a toString() method (defined in the root
class java.lang.Object), which returns the string representation of
that object. Each of the standard collection classes in java.util
defines its toString() method to recursively call toString() on its
elements.

For example, the program

import java.util.*;
public class Foo {
public static void main(String[] args) {
List lst = new ArrayList();
lst.add("a");
lst.add("b");
lst.add("c");
System.out.println(lst);
}
}

prints "[a, b, c]".

(Btw, this reminds me of something I like about Python: There are
literals for variable length arrays, so you don't have to write code
like that.)

The difference from Python's approach is that there isn't an
equivalent to Python's str/repr distinction. Obviously, when there's
only one string conversion method, you won't use the wrong one.

The other difference is that the built-in array types don't have a
meaningful toString() method, so

public class Foo {
public static void main(String[] args) {
String[] arr = {"a", "b", "c"};
System.out.println(arr);
}
}

prints "[Ljava.lang.String;@df6ccd" (or something similar).
 
D

Donn Cave

All Java classes include a toString() method (defined in the root
class java.lang.Object), which returns the string representation of
that object. Each of the standard collection classes in java.util
defines its toString() method to recursively call toString() on its
elements.

For example, the program

import java.util.*;
public class Foo {
public static void main(String[] args) {
List lst = new ArrayList();
lst.add("a");
lst.add("b");
lst.add("c");
System.out.println(lst);
}
}

prints "[a, b, c]".

OK, so it's ambiguous - you don't know from the result
whether there are three elements, or two or one - if
one of the elements has its own ", ".
(Btw, this reminds me of something I like about Python: There are
literals for variable length arrays, so you don't have to write code
like that.)

The difference from Python's approach is that there isn't an
equivalent to Python's str/repr distinction. Obviously, when there's
only one string conversion method, you won't use the wrong one.

It would be fun to apply that reasoning to arithmetic
operators. Which one does Java support?
The other difference is that the built-in array types don't have a
meaningful toString() method, so

public class Foo {
public static void main(String[] args) {
String[] arr = {"a", "b", "c"};
System.out.println(arr);
}
}

prints "[Ljava.lang.String;@df6ccd" (or something similar).

Ah, I can see how appealing this system would be.
What elegance!

Donn Cave, (e-mail address removed)
 
D

Dan Bishop

Donn Cave said:
All Java classes include a toString() method (defined in the root
class java.lang.Object), which returns the string representation of
that object...[big snip]
The difference from Python's approach is that there isn't an
equivalent to Python's str/repr distinction. Obviously, when there's
only one string conversion method, you won't use the wrong one.

It would be fun to apply that reasoning to arithmetic
operators. Which one does Java support?

toString() usually behaves more like Python's str than repr. An
exception is Double.toString, which returns 16 signifcant digits.

Jython uses toString() to implement both __str__ and __repr__ for Java
classes.
 
J

John Roth

George Sakkis said:
Hi all,

I find the string representation behaviour of builtin containers
(tuples,lists,dicts) unintuitive in that they don't call recursively str()
on their contents (e.g. as in Java) :
It's even more cumbersome for containers of containers (e.g. lists of dicts,
etc.). Of course one can (or should) encapsulate such stuctures in a class
and define __str__ to behave as expected, but why not having it by default ?
Is there a good reason for this ?

I don't think there's a ***good*** reason. The root of
the issue is that the str() / repr() distinction is too simplistic
for containers. The output of str() is supposed to be human
readable, and the output of repr() is supposed to be able
to round-trip through exec/eval (which is not always possible,
but should be maintained if it is.)

Human readable output from a container, however, needs
to be very clear on the distinction between the container
and the objects that are contained. It isn't always obvious
whether using str() or repr() on the contained object is the
best policy, and in some cases I suspect that something
different from either would be helpful.

The only clean solution I can see is to provide a third built-in
that provides the "right" output when a container class needs
to turn an object into a string. However, someone else
is going to have to do the work of writing up the use
cases and the PEP - I don't care enough.

John Roth
 
M

Marcin 'Qrczak' Kowalczyk

The only clean solution I can see is to provide a third built-in
that provides the "right" output when a container class needs
to turn an object into a string.

What is the right thing e.g. for strings?
 
E

Edward C. Jones

John said:
The only clean solution I can see is to provide a third built-in
that provides the "right" output when a container class needs
to turn an object into a string. However, someone else
is going to have to do the work of writing up the use
cases and the PEP - I don't care enough.

For str of a container, I suggest using repr for strings in the
container and str for everything else.
 
D

Donn Cave

Quoth "John Roth" <[email protected]>:
....
| I don't think there's a ***good*** reason. The root of
| the issue is that the str() / repr() distinction is too simplistic
| for containers. The output of str() is supposed to be human
| readable, and the output of repr() is supposed to be able
| to round-trip through exec/eval (which is not always possible,
| but should be maintained if it is.)

That's one way to look at it, but it's a perspective that will
always leave you dissatisfied with both str and repr.

Not only is repr-as-marshal not always possible, it's very widely
not implemented even when it could be, and anyone who relies on
this feature is asking for trouble. Human readable is as vacuous
an expectation as there could be for what str does, so it's hard
to say for sure you'll be disappointed there, but then it's just
impossible to imagine any solid basis for saying whether a value
is going to be human readable. I've seen what the documentation
says, and there has been plenty of discussion about this.

The way I see it, __str__ is about conversion to string data. It
really applies to only those objects that can naturally be converted
to a string. If lists had a __str__ function, then str(list) would
be the inverse of list(str), but since that would raise all kinds
of questions about what to do with lists containing other things
besides strings of length 1, there is no __str__ function. Instead,
str(list) calls __repr__.

Repr renders the object as a string. Not just the object's value
in a computational sense, so to speak, but the object implementation.
So it's typically more interesting to a programmer, than the program's
user. That could be seen as a human readability issue, but it puts
the point into better perspective - what's the user-oriented value
of a list as string? There isn't one.

Donn Cave, (e-mail address removed)
 

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

Similar Threads


Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top