It is becoming the norm in 3.x for functions to return iterators, generators, or views whereever possible. I had a thought that pprint() ought to be taught to print iterators: pprint(enumerate(seq)) pprint(map(somefunc, somedata)) pprint(permutations(elements)) pprint(mydict.items()) Currently, all four of those will print something like: >>> pprint(d.items()) <dict_items object at 0x00FA4470> >>> pprint(enumerate(d)) <enumerate object at 0x00FC2878> If pprint() is to give a more useful result, the question is how best to represent the iterators. In the examples for itertools, I adopted the convention of displaying results like a collection with no commas or enclosing delimiters: # chain('ABC', 'DEF') --> A B C D E F The equivalent for pprint would be the same for items, using space for items on one row or using linefeeds for output too long for one row. Another idea is to make-up an angle-bracket style to provide a visual cue for iterator output: <'A' 'B' 'C' 'D' 'E' 'F'> Perhaps with commas: <'A', 'B', 'C', 'D', 'E', 'F'> None of those ideas can be run through eval, nor do they identify the type of iterator. Perhaps these would be better: <enumerate object: 'A', 'B', 'C', 'D', 'E', 'F'> or iter(['A', 'B', 'C', 'D', 'E', 'F']) Do you guys have any thoughts on the subject? Raymond
My only thought is that whatever you do, target Python 3.1, not 3.0.1. On Tue, Jan 27, 2009 at 1:46 PM, Raymond Hettinger <python@rcn.com> wrote:
It is becoming the norm in 3.x for functions to return iterators, generators, or views whereever possible.
I had a thought that pprint() ought to be taught to print iterators:
pprint(enumerate(seq)) pprint(map(somefunc, somedata)) pprint(permutations(elements)) pprint(mydict.items())
Currently, all four of those will print something like:
pprint(d.items()) <dict_items object at 0x00FA4470> pprint(enumerate(d)) <enumerate object at 0x00FC2878>
If pprint() is to give a more useful result, the question is how best to represent the iterators.
In the examples for itertools, I adopted the convention of displaying results like a collection with no commas or enclosing delimiters:
# chain('ABC', 'DEF') --> A B C D E F
The equivalent for pprint would be the same for items, using space for items on one row or using linefeeds for output too long for one row.
Another idea is to make-up an angle-bracket style to provide a visual cue for iterator output:
<'A' 'B' 'C' 'D' 'E' 'F'>
Perhaps with commas:
<'A', 'B', 'C', 'D', 'E', 'F'>
None of those ideas can be run through eval, nor do they identify the type of iterator. Perhaps these would be better:
<enumerate object: 'A', 'B', 'C', 'D', 'E', 'F'>
or
iter(['A', 'B', 'C', 'D', 'E', 'F'])
Do you guys have any thoughts on the subject?
Raymond _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/guido%40python.org
-- --Guido van Rossum (home page: http://www.python.org/~guido/)
On Tue, Jan 27, 2009 at 2:24 PM, Raymond Hettinger <python@rcn.com> wrote:
[Guido van Rossum]
My only thought is that whatever you do, target Python 3.1, not 3.0.1.
Of course. Do you have any thoughts on the most useful display format? What do you want to see from pprint(mydict.items())?
Perhaps <['a', 'b', ...]> ? The list display is familiar to everyone; the surrounding <> make it clear that it's not really a list without adding much noise. Another idea would be <dict_items: ['a', 'b', ...]> which helpfully includes the name of the type of the object that was passed into pprint(). Regarding range(), I wonder if we really need to show more than 'range(0, 10)' -- anything besides that would be wasteful IMO. -- --Guido van Rossum (home page: http://www.python.org/~guido/)
On Tue, Jan 27, 2009 at 01:46:35PM -0800, Raymond Hettinger wrote:
<enumerate object: 'A', 'B', 'C', 'D', 'E', 'F'>
I like the idea, and I prefer this formatting. Also bear in mind there are infinite generators, and there are iterators that cannot be reset. For infinite generators pprint() must have a parameter, say, 'max_items', and print <generator: 'A', 'B', 'C', 'D', 'E', 'F', ...>. The situation with iterators that cannot be reset should be documented. Oleg. -- Oleg Broytmann http://phd.pp.ru/ phd@phd.pp.ru Programmers don't die, they just GOSUB without RETURN.
On Tue, Jan 27, 2009 at 2:06 PM, Oleg Broytmann <phd@phd.pp.ru> wrote:
On Tue, Jan 27, 2009 at 01:46:35PM -0800, Raymond Hettinger wrote:
<enumerate object: 'A', 'B', 'C', 'D', 'E', 'F'>
I like the idea, and I prefer this formatting. Also bear in mind there are infinite generators, and there are iterators that cannot be reset. For infinite generators pprint() must have a parameter, say, 'max_items', and print <generator: 'A', 'B', 'C', 'D', 'E', 'F', ...>. The situation with iterators that cannot be reset should be documented.
This pretty much kills the proposal. Calling a "print" function like pprint() should not have a side effect on the object being printed. I'd be okay of pprint() special-cased the views returned by e.g. dict.keys(), but if all we know is that the argument has a __next__ method, pprint() should *not* be calling that. -- --Guido van Rossum (home page: http://www.python.org/~guido/)
On Tue, Jan 27, 2009 at 3:46 PM, Raymond Hettinger <python@rcn.com> wrote:
It is becoming the norm in 3.x for functions to return iterators, generators, or views whereever possible.
Do you guys have any thoughts on the subject?
Maybe a solution like this could help with bugs like #2610? -- Regards, Benjamin
On Tue, Jan 27, 2009 at 2:12 PM, Benjamin Peterson <benjamin@python.org> wrote:
On Tue, Jan 27, 2009 at 3:46 PM, Raymond Hettinger <python@rcn.com> wrote:
It is becoming the norm in 3.x for functions to return iterators, generators, or views whereever possible.
Do you guys have any thoughts on the subject?
Maybe a solution like this could help with bugs like #2610?
It would have to special-case range() objects. -- --Guido van Rossum (home page: http://www.python.org/~guido/)
Raymond Hettinger wrote:
<enumerate object: 'A', 'B', 'C', 'D', 'E', 'F'>
I quite like the idea of something along those lines. For example: try: itr = iter(obj) except TypeError: pass else: return "<iterable %s: %s>" % (obj.__class__.__name__, <as for list contents>)) Doing this only in pprint also reduces the chances of accidentally consuming an iterator (which was a reasonable objection when I suggested changing the __str__ implementation on some of the standard iterators some time ago). Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia ---------------------------------------------------------------
On Tue, Jan 27, 2009, Raymond Hettinger wrote:
It is becoming the norm in 3.x for functions to return iterators, generators, or views whereever possible.
I had a thought that pprint() ought to be taught to print iterators:
pprint(enumerate(seq)) pprint(map(somefunc, somedata)) pprint(permutations(elements)) pprint(mydict.items())
Along the lines of what others have said: pprint() cannot consume an unknown iterator. Therefore, you can pretty up the existing output slightly or special-case certain known iterators. There might also be an API change to pprint() that allowed it to consume iterators. The reason I'm chiming in is that I would welcome a PEP that created a __pprint__ method as an alternative to special-casing. I think that it would be generically useful for user-created objects, plus once you've added this feature other people can easily do some of the grunt work of extending this through the Python core. (Actually, unless someone objects, I don't think a PEP is required, but it would be good for the usual reasons that PEPs are written, to provide a central place documenting the addition.) This can also be done for Python 2.7, too. -- Aahz (aahz@pythoncraft.com) <*> http://www.pythoncraft.com/ Weinberg's Second Law: If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilization.
Aahz wrote:
On Tue, Jan 27, 2009, Raymond Hettinger wrote:
It is becoming the norm in 3.x for functions to return iterators, generators, or views whereever possible.
I had a thought that pprint() ought to be taught to print iterators:
pprint(enumerate(seq)) pprint(map(somefunc, somedata)) pprint(permutations(elements)) pprint(mydict.items())
Along the lines of what others have said: pprint() cannot consume an unknown iterator. Therefore, you can pretty up the existing output slightly or special-case certain known iterators. There might also be an API change to pprint() that allowed it to consume iterators.
The reason I'm chiming in is that I would welcome a PEP that created a __pprint__ method as an alternative to special-casing. I think that it would be generically useful for user-created objects, plus once you've added this feature other people can easily do some of the grunt work of extending this through the Python core. (Actually, unless someone objects, I don't think a PEP is required, but it would be good for the usual reasons that PEPs are written, to provide a central place documenting the addition.)
This can also be done for Python 2.7, too.
Don't we have a pretty-print API - and isn't it spelled __str__ ? Michael Foord -- http://www.ironpythoninaction.com/ http://www.voidspace.org.uk/blog
On Thu, Jan 29, 2009, Michael Foord wrote:
Aahz wrote:
On Tue, Jan 27, 2009, Raymond Hettinger wrote:
It is becoming the norm in 3.x for functions to return iterators, generators, or views whereever possible.
I had a thought that pprint() ought to be taught to print iterators:
pprint(enumerate(seq)) pprint(map(somefunc, somedata)) pprint(permutations(elements)) pprint(mydict.items())
The reason I'm chiming in is that I would welcome a PEP that created a __pprint__ method as an alternative to special-casing. I think that it would be generically useful for user-created objects, plus once you've added this feature other people can easily do some of the grunt work of extending this through the Python core. (Actually, unless someone objects, I don't think a PEP is required, but it would be good for the usual reasons that PEPs are written, to provide a central place documenting the addition.)
Don't we have a pretty-print API - and isn't it spelled __str__ ?
In theory, yes. In practice, we wouldn't be having this discussion if that really worked. But it probably would make sense to see how far using __str__ can take us -- AFAICT enumobject.c doesn't define __str__ (although I may be missing something, I don't know Python at the C level very well). -- Aahz (aahz@pythoncraft.com) <*> http://www.pythoncraft.com/ Weinberg's Second Law: If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilization.
On Thu, Jan 29, 2009 at 08:06:18AM -0800, Aahz wrote:
On Thu, Jan 29, 2009, Michael Foord wrote:
Don't we have a pretty-print API - and isn't it spelled __str__ ?
In theory, yes. In practice, we wouldn't be having this discussion if that really worked. But it probably would make sense to see how far using __str__ can take us -- AFAICT enumobject.c doesn't define __str__ (although I may be missing something, I don't know Python at the C level very well).
Container objects (tuples/lists/dicts/sets) don't define __str__. Is __pprint__ an attempt to redefine __str__? Oleg. -- Oleg Broytmann http://phd.pp.ru/ phd@phd.pp.ru Programmers don't die, they just GOSUB without RETURN.
2009/1/29 Oleg Broytmann <phd@phd.pp.ru>:
On Thu, Jan 29, 2009 at 08:06:18AM -0800, Aahz wrote:
On Thu, Jan 29, 2009, Michael Foord wrote:
Don't we have a pretty-print API - and isn't it spelled __str__ ?
In theory, yes. In practice, we wouldn't be having this discussion if that really worked. But it probably would make sense to see how far using __str__ can take us -- AFAICT enumobject.c doesn't define __str__ (although I may be missing something, I don't know Python at the C level very well).
Container objects (tuples/lists/dicts/sets) don't define __str__. Is __pprint__ an attempt to redefine __str__?
Anyone feel like raising the topic of generic functions again? :-) More practically, the undocumented simplegeneric decorator in pkgutil could be used: Python 2.6.1 (r261:67517, Dec 4 2008, 16:51:00) [MSC v.1500 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information.
from pkgutil import simplegeneric @simplegeneric ... def f(obj): ... return "Object of type %s" % type(obj) ... def str_f(s): ... return "String: " + s ... f.register(str, str_f) <function str_f at 0x00B461F0> f("Test") 'String: Test' f(1) "Object of type <type 'int'>"
To me, that seems better than inventing yet another special method. Paul.
Michael Foord wrote:
Don't we have a pretty-print API - and isn't it spelled __str__ ?
For the "reiterable" cases like dictionary views (where the object is not consumed), an appropriate __str__ or __repr__ should be written). Whether that is something as simple as "<repr of underlying dict>.items()" for an items view, or something more complicated that more directly shows the content of the view, I'm not sure. For the standard iterators like enumerate and ranged, I would suggest that they be modified to use a repr of the form: "reversed(<repr of underlying iterable>)" "enumerate(<repr of underlying iterable>)" "iter(<repr of underlying sequence>)" "iter(<repr of callable>, <repr of sentinel value>)" While those obviously won't show how much of the iterable has been consumed, neither do the current representations. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia ---------------------------------------------------------------
On 29 Jan 2009, at 21:54, Nick Coghlan wrote:
For the "reiterable" cases like dictionary views (where the object is not consumed), an appropriate __str__ or __repr__ should be written).
Indeed, instead of having a __pprint__ why not just allow a __repr__ to reformat its output? dict having: def __repr__(self, pretty=False): if pretty: return "{\n a: 1\n b: 2\n}" else: return "{a: 1, b: 2}" That way you can specify your own pretty format, intending it to still be a valid __repr__ and pprint can do: try: print(obj.__repr__(pretty=True)) except TypeError: print(prettify(repr(obj))) That way it's opt in, doesn't have a special method, and includes the mental prompt "this should eval() to obj" Matt
Michael Foord wrote:
Don't we have a pretty-print API - and isn't it spelled __str__ ?
Not really. If it were as simple as calling str(obj), there would be no need for the pprint module. In any case, it seems that the pprint module actually calls repr() on objects other than dicts, tuples and lists. I'm concerned about the number of special methods exploding, but I've also come across times where I needed more than two string representations of an object. Sometimes I solved this by adding a pprint() method, other times I used other names, and it would be nice if there was a standard way of spelling it. So I'm +0.5 on Aahz's suggestion of __pprint__. In my ideal world, __pprint__ should allow (but not require) extra arguments, so that one can do something like the following: pprint(binarytree) # sensible defaults pprint(binarytree, order='preorder') -- Steven
Steven D'Aprano wrote:
Michael Foord wrote:
Don't we have a pretty-print API - and isn't it spelled __str__ ?
Not really. If it were as simple as calling str(obj), there would be no need for the pprint module.
I agree. And when I want to use pprint, there are usually additional output formatting requirements I need that isn't a "one size fits all" type of problem. In any case, it seems that the pprint module
actually calls repr() on objects other than dicts, tuples and lists.
I'm concerned about the number of special methods exploding, but I've also come across times where I needed more than two string representations of an object. Sometimes I solved this by adding a pprint() method, other times I used other names, and it would be nice if there was a standard way of spelling it. So I'm +0.5 on Aahz's suggestion of __pprint__.
I'm -.5 on addint __pprint__ for the above reasons.
In my ideal world, __pprint__ should allow (but not require) extra arguments, so that one can do something like the following:
pprint(binarytree) # sensible defaults pprint(binarytree, order='preorder')
It seems to me pprint is one of those functions where output format specifiers and keywords make sense because you are trying to fit the data output of a wide variety of types to a particular output need. It's not reasonably possible for each type to predict what that output need is. Some of the options that sound useful might be: abbreviated form short form long complete detail form tree form column align form right or left margins and alignment options Think of it as how 'dir' is used for examining the contents of a disk drive where different output styles is useful at different times. Looking at it this way, instead of a __pprint__ method, a optional __pprint_style__ attribute could specify a default output style that the pprint function would fall back to. Maybe for iterators, it's not the data produced but rather the current state of use that is more useful? For example for partially consumed iterators it might be useful to express how many items have been taken, and how many are left to take when that info is available. (?) The idea is that pretty printing is usually used to check the status or state of something. Or at least that is how I use it. Ron
Ron Adam wrote:
Steven D'Aprano wrote:
Michael Foord wrote:
Don't we have a pretty-print API - and isn't it spelled __str__ ?
Not really. If it were as simple as calling str(obj), there would be no need for the pprint module.
I agree. And when I want to use pprint, there are usually additional output formatting requirements I need that isn't a "one size fits all" type of problem.
Like others, I am wary of over-expanding the list of special methods. Perhap format strings could have a fourth conversion specifier, !p (pretty) in addition to !s, !r, and !a.
Terry Reedy wrote:
Ron Adam wrote:
Steven D'Aprano wrote:
Michael Foord wrote:
Don't we have a pretty-print API - and isn't it spelled __str__ ?
Not really. If it were as simple as calling str(obj), there would be no need for the pprint module.
I agree. And when I want to use pprint, there are usually additional output formatting requirements I need that isn't a "one size fits all" type of problem.
I don't see how you can have a standard interface (like __pprint__), and have additional, per-object formatting parameters. But that's beside the point, I don't like __pprint__ in any event. Too special.
Like others, I am wary of over-expanding the list of special methods. Perhap format strings could have a fourth conversion specifier, !p (pretty) in addition to !s, !r, and !a.
What would format() do with "!p"? With "!s", it calls str(o), with "!r", it calls repr(o). "!p" could call o.__pprint__(), but that's the special method you're trying to avoid! (I don't recall if I added "!a", and a machine that would know isn't available to me just now.) Eric.
Eric Smith wrote:
Terry Reedy wrote:
Ron Adam wrote:
Steven D'Aprano wrote:
Michael Foord wrote:
Don't we have a pretty-print API - and isn't it spelled __str__ ?
Not really. If it were as simple as calling str(obj), there would be no need for the pprint module.
I agree. And when I want to use pprint, there are usually additional output formatting requirements I need that isn't a "one size fits all" type of problem.
I don't see how you can have a standard interface (like __pprint__), and have additional, per-object formatting parameters.
I don't see how you can't. Other standard methods take variable arguments: __init__, __new__, __call__ come to mind.
But that's beside the point, I don't like __pprint__ in any event. Too special.
I'm not sure what you mean by "too special". It's no more special than any other special method. Do you mean the use-case is not common enough? I would find this useful. Whether enough people would find it useful enough to add yet another special method is an open question. -- Steven
2009/1/30 Steven D'Aprano <steve@pearwood.info>:
But that's beside the
point, I don't like __pprint__ in any event. Too special.
I'm not sure what you mean by "too special". It's no more special than any other special method. Do you mean the use-case is not common enough? I would find this useful. Whether enough people would find it useful enough to add yet another special method is an open question.
In my view, the issue is that as a special method, *either* it has to be included on all core types (too intrusive for something as non-critical as pprint) *or* pprint has to hard-code the behaviour for core types and still fall back to the special method for non-core types (ugly and a maintenance problem keeping the type tests up to date). Some sort of registry of type-specific implementation functions (whether you call it a generic function or just put together a custom implementation for pprint alone) is more flexible, and less intrusive. It also allows end users to customise the behaviour, even for core types. In all honesty, I think pkgutil.simplegeneric should be documented, exposed, and moved to a library of its own[1]. It's precisely what is needed for this type of situation, which does come up fairly often. I don't think ABCs do what's needed here (although maybe I'm missing something - if so, I'd be interested in knowing what). I'd be willing to look at creating a patch, if the consensus was that this was an appropriate approach and there was a reasonable chance of it being accepted (assuming my code wasn't rubbish :-)) Paul. [1] Note - I have no opinion on the quality of the code, I haven't reviewed it, I am assuming it's OK on the basis that it has been present and in use internally in the pkgutil module for some time now.
Paul Moore wrote:
[...] In all honesty, I think pkgutil.simplegeneric should be documented, exposed, and moved to a library of its own[1].
http://pypi.python.org/pypi/simplegeneric
[...]
Servus, Walter
2009/1/30 Walter Dörwald <walter@livinglogic.de>:
Paul Moore wrote:
[...] In all honesty, I think pkgutil.simplegeneric should be documented, exposed, and moved to a library of its own[1].
Thanks, I was aware of that. I assume that the barrier to getting this into the stdlib will be higher than to simply exposing an implementation already available in the stdlib. To be honest, all I would like is for these regular "let's have another special method" discussions to become unnecessary... Paul.
Paul Moore wrote:
2009/1/30 Walter Dörwald <walter@livinglogic.de>:
Paul Moore wrote:
[...] In all honesty, I think pkgutil.simplegeneric should be documented, exposed, and moved to a library of its own[1]. http://pypi.python.org/pypi/simplegeneric
Thanks, I was aware of that.
I wasn't aware of the fact that simplegeneric is part of the stdlib, albeit in a strange spot.
I assume that the barrier to getting this into the stdlib will be higher than to simply exposing an implementation already available in the stdlib.
At least we'd need documentation and tests. And of course the code must be stable and there must be someone willing to maintain it (then again it's less than 40 lines of code). There should be enough third-party module that use it to justify making simplegeneric an official part of the stdlib. The best spot for generic() is probably in the functools module.
To be honest, all I would like is for these regular "let's have another special method" discussions to become unnecessary...
Me too. Servus, Walter
Walter Dörwald wrote:
Paul Moore wrote:
2009/1/30 Walter Dörwald <walter@livinglogic.de>:
Paul Moore wrote:
[...] In all honesty, I think pkgutil.simplegeneric should be documented, exposed, and moved to a library of its own[1]. http://pypi.python.org/pypi/simplegeneric
Thanks, I was aware of that.
I wasn't aware of the fact that simplegeneric is part of the stdlib, albeit in a strange spot.
Officially, it isn't - it's an implementation detail of pkgutil. As such, a leading underscore wouldn't have hurt, but the lack of mention in the pkgutil documentation (or pkgutil.__all__) is hopefully enough of a hint that it really isn't intended as a general purpose programming tool.
I assume that the barrier to getting this into the stdlib will be higher than to simply exposing an implementation already available in the stdlib.
At least we'd need documentation and tests. And of course the code must be stable and there must be someone willing to maintain it (then again it's less than 40 lines of code).
There should be enough third-party module that use it to justify making simplegeneric an official part of the stdlib.
The best spot for generic() is probably in the functools module.
To be honest, all I would like is for these regular "let's have another special method" discussions to become unnecessary...
Me too.
A trio of patches that: 1. promoted simplegeneric from pkgutil to functools (with appropriate documentation and tests) 2. changed pkgutil to use functools.simplegeneric instead of its current internal version 3. updated pprint to be a generic function (and hence more easily extensible via the ABC mechanism, while still keeping it's current special cases as necessary) would certainly be an interesting thing to see (with patch 3 being the poster child for why patch 1 is a good idea). The major virtue of such a basic generic framework is that it is much easier to explain than the all-singing all-dancing overloading system described in PEP 3124. Type-based dispatch on the first argument is fairly straightforward to describe in terms that make sense to anyone that is already familiar with dynamic dispatch of class and instance methods. It's only when you get into more exotic dispatch conditions and up-calls and the like that people's eyes start to glaze over. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia ---------------------------------------------------------------
2009/2/2 Nick Coghlan <ncoghlan@gmail.com>:
A trio of patches that: 1. promoted simplegeneric from pkgutil to functools (with appropriate documentation and tests) 2. changed pkgutil to use functools.simplegeneric instead of its current internal version 3. updated pprint to be a generic function (and hence more easily extensible via the ABC mechanism, while still keeping it's current special cases as necessary)
would certainly be an interesting thing to see (with patch 3 being the poster child for why patch 1 is a good idea).
I'll see what I can do. I can't promise much for (3) as I don't personally have a need for it, so my understanding of the use cases is limited at best. But (1) and (2) should be possible. Can I assign the patches to you (for review, at least)?
The major virtue of such a basic generic framework is that it is much easier to explain than the all-singing all-dancing overloading system described in PEP 3124. Type-based dispatch on the first argument is fairly straightforward to describe in terms that make sense to anyone that is already familiar with dynamic dispatch of class and instance methods. It's only when you get into more exotic dispatch conditions and up-calls and the like that people's eyes start to glaze over.
Agreed. And given that the simple case probably covers 90% of the practical requirements, that's a shame. Paul.
Paul Moore wrote:
2009/2/2 Nick Coghlan <ncoghlan@gmail.com>:
A trio of patches that: 1. promoted simplegeneric from pkgutil to functools (with appropriate documentation and tests) 2. changed pkgutil to use functools.simplegeneric instead of its current internal version 3. updated pprint to be a generic function (and hence more easily extensible via the ABC mechanism, while still keeping it's current special cases as necessary)
would certainly be an interesting thing to see (with patch 3 being the poster child for why patch 1 is a good idea).
I'll see what I can do. I can't promise much for (3) as I don't personally have a need for it, so my understanding of the use cases is limited at best. But (1) and (2) should be possible.
Can I assign the patches to you (for review, at least)?
Sure - I've had plenty to do with functools in the past, and will no doubt have plenty to do with it in the future. Given that I believe Guido was one of the folks whose brain was hurt by PJE's attempts to explain PEP 3124, I'll be bringing the discussion back here before committing anything though :) (and don't worry too much about 3 - it will give me an opportunity to road test the functools patch by using it to refactor pprint and check the performance implications) Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia ---------------------------------------------------------------
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Nick Coghlan wrote:
Paul Moore wrote:
A trio of patches that: 1. promoted simplegeneric from pkgutil to functools (with appropriate documentation and tests) 2. changed pkgutil to use functools.simplegeneric instead of its current internal version 3. updated pprint to be a generic function (and hence more easily extensible via the ABC mechanism, while still keeping it's current special cases as necessary)
would certainly be an interesting thing to see (with patch 3 being the poster child for why patch 1 is a good idea). I'll see what I can do. I can't promise much for (3) as I don't
2009/2/2 Nick Coghlan <ncoghlan@gmail.com>: personally have a need for it, so my understanding of the use cases is limited at best. But (1) and (2) should be possible.
Can I assign the patches to you (for review, at least)?
Sure - I've had plenty to do with functools in the past, and will no doubt have plenty to do with it in the future.
Given that I believe Guido was one of the folks whose brain was hurt by PJE's attempts to explain PEP 3124, I'll be bringing the discussion back here before committing anything though :)
(and don't worry too much about 3 - it will give me an opportunity to road test the functools patch by using it to refactor pprint and check the performance implications)
/me wonders about the performance-criticality of anything using 'pprint'. Or were you just planning to use it as a means to benchmark the 'simplegeneric' stuff? I would think something with a lot lower intrinsic overhead would be a better benchmark target. Tres. - -- =================================================================== Tres Seaver +1 540-429-0999 tseaver@palladion.com Palladion Software "Excellence by Design" http://palladion.com -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFJhu6I+gerLs4ltQ4RAvdcAJ4mFTcdfgG7ZVvdKXulIw+fWgLJxwCeOrTO 9rriK3+zyl4K63doUjbckF4= =++qD -----END PGP SIGNATURE-----
Tres Seaver wrote:
Nick Coghlan wrote:
(and don't worry too much about 3 - it will give me an opportunity to road test the functools patch by using it to refactor pprint and check the performance implications)
/me wonders about the performance-criticality of anything using 'pprint'. Or were you just planning to use it as a means to benchmark the 'simplegeneric' stuff? I would think something with a lot lower intrinsic overhead would be a better benchmark target.
Don't read too much into that comment - generics make the most sense in cases (like pprint) where extensibility is a more important feature than raw speed. I'm talking about more subjective impressions of performance as well as things like "if I register a handler for Sequence, is there any performance advantage in registering direct handlers for the builtin subclasses?". Really drastic performance degradations would be on the radar as well - slowing pprint() down by 10% is unlikely to bother anyone, but slowing it down by 100% would be a bad thing (not that I think such a degradation is likely, I'm just trying to give an impression of the magnitude of change I'll be trying to measure). Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia ---------------------------------------------------------------
On 2009-02-02 14:50, Nick Coghlan wrote:
Really drastic performance degradations would be on the radar as well - slowing pprint() down by 10% is unlikely to bother anyone, but slowing it down by 100% would be a bad thing (not that I think such a degradation is likely, I'm just trying to give an impression of the magnitude of change I'll be trying to measure).
Using the pretty module I referenced earlier, which basically uses simplegeneric's lookup algorithm: In [11]: %timeit x=pprint.pformat(sys.modules) 10 loops, best of 3: 27.5 ms per loop In [12]: %timeit x=pretty.pretty(sys.modules) 10 loops, best of 3: 39.9 ms per loop In [13]: len(sys.modules) Out[13]: 517 The comparison is somewhat dodgy, though. pretty is not so much a refactoring of pprint as a reimplementation, so the time differences may not be due to the dispatch. -- Robert Kern "I have come to believe that the whole world is an enigma, a harmless enigma that is made terrible by our own mad attempt to interpret it as though it had an underlying truth." -- Umberto Eco
2009/2/2 Nick Coghlan <ncoghlan@gmail.com>:
Paul Moore wrote:
2009/2/2 Nick Coghlan <ncoghlan@gmail.com>:
A trio of patches that: 1. promoted simplegeneric from pkgutil to functools (with appropriate documentation and tests) 2. changed pkgutil to use functools.simplegeneric instead of its current internal version 3. updated pprint to be a generic function (and hence more easily extensible via the ABC mechanism, while still keeping it's current special cases as necessary)
would certainly be an interesting thing to see (with patch 3 being the poster child for why patch 1 is a good idea).
I'll see what I can do. I can't promise much for (3) as I don't personally have a need for it, so my understanding of the use cases is limited at best. But (1) and (2) should be possible.
Can I assign the patches to you (for review, at least)?
Sure - I've had plenty to do with functools in the past, and will no doubt have plenty to do with it in the future.
http://bugs.python.org/issue5135 A single patch covering (1) and (2). Paul.
Steven D'Aprano wrote:
Eric Smith wrote:
Terry Reedy wrote:
Ron Adam wrote:
Steven D'Aprano wrote:
Michael Foord wrote:
Don't we have a pretty-print API - and isn't it spelled __str__ ?
Not really. If it were as simple as calling str(obj), there would be no need for the pprint module.
I agree. And when I want to use pprint, there are usually additional output formatting requirements I need that isn't a "one size fits all" type of problem.
I don't see how you can have a standard interface (like __pprint__), and have additional, per-object formatting parameters.
I don't see how you can't. Other standard methods take variable arguments: __init__, __new__, __call__ come to mind.
Those are different, since they're called on known specific objects. Having params to a generic __pprint__ method would be more like having params to __str__ or __repr__. If you know enough about the object to know which parameters to pass to its pretty-print function, then just call a normal method on the object to do the pprint'ing. But, for example, assuming pprint for a list is recursive (as it is for repr), how would you pass the arguments around?
But that's beside the point, I don't like __pprint__ in any event. Too special.
I'm not sure what you mean by "too special". It's no more special than any other special method. Do you mean the use-case is not common enough? I would find this useful. Whether enough people would find it useful enough to add yet another special method is an open question.
Bad choice of words on my part. I meant "too special case" for such machinery. That is, the use case isn't common enough.
On 2009-01-29 08:20, Aahz wrote:
The reason I'm chiming in is that I would welcome a PEP that created a __pprint__ method as an alternative to special-casing. I think that it would be generically useful for user-created objects, plus once you've added this feature other people can easily do some of the grunt work of extending this through the Python core. (Actually, unless someone objects, I don't think a PEP is required, but it would be good for the usual reasons that PEPs are written, to provide a central place documenting the addition.)
I think it's worth looking at Armin Ronacher's pretty.py for a starting point. http://dev.pocoo.org/hg/sandbox/file/tip/pretty I've been using it as my default displayhook under IPython for a few weeks now. It uses a combination of a function registry and a __pretty__ special method to find the right pretty printer. -- Robert Kern "I have come to believe that the whole world is an enigma, a harmless enigma that is made terrible by our own mad attempt to interpret it as though it had an underlying truth." -- Umberto Eco
Along the lines of what others have said: pprint() cannot consume an unknown iterator.
Perhaps so. It's nice to have printing be free of side-effects (other than the actual printing). I've been working with 3.0 daily for several months (on a book project) and mostly think it's great. But sooner or later, we're going to have to address the issue about iterator reprs at the interactive prompt. This is a separate and more general issue than pprint(). My experience so far is that it is that the shift to more things being unviewable at the prompt is bit frustrating and makes the language more opaque. If that has been a source of irritation to me, then it will likely be more acutely felt by people who are starting out and are using the interactive prompt to explore the language. I don't know the right answer here (perhaps an alternate sys.displayhook). Just wanted to provide some early feedback based on my experiences heavily exercising 3.0. Raymond P.S. My other experience with 3.0 is that my most frequent error has changed. It used to be that the number reason for my getting a syntax error was leaving-off a colon. Now, my number one reason is omitting parens in a print() function call. I thought I would get used to it quickly, but it still comes up several times a day.
Raymond Hettinger <python <at> rcn.com> writes:
P.S. My other experience with 3.0 is that my most frequent error has changed. It used to be that the number reason for my getting a syntax error was leaving-off a colon. Now, my number one reason is omitting parens in a print() function call. I thought I would get used to it quickly, but it still comes up several times a day.
I find myself with the reverse problem. When I code with 2.x, I often put parens around the argument list of a print staement.
participants (17)
-
Aahz
-
Antoine Pitrou
-
Benjamin Peterson
-
Eric Smith
-
Guido van Rossum
-
Matthew Wilkes
-
Michael Foord
-
Nick Coghlan
-
Oleg Broytmann
-
Paul Moore
-
Raymond Hettinger
-
Robert Kern
-
Ron Adam
-
Steven D'Aprano
-
Terry Reedy
-
Tres Seaver
-
Walter Dörwald