From: Charles R H. <cha...@gm...> - 2006-08-29 23:17:37
|
On 8/29/06, Charles R Harris <cha...@gm...> wrote: > > On 8/29/06, Tim Hochberg <tim...@ie...> wrote: > > > David M. Cooke wrote: > > > On Tue, 29 Aug 2006 14:03:39 -0700 > > > Tim Hochberg <tim...@ie...> wrote: > > > > > > > > >> Of these, clip, conjugate and round support an 'out' argument like > > that > > >> supported by ufunces; byteswap has a boolean argument telling it > > >> whether to perform operations in place; and sort always operates in > > >> place. Noting that the ufunc-like methods (max, argmax, etc) appear > > to > > >> support the 'out' argument as well although it's not documented for > > most > > >> of them, it looks to me as if the two odd methods are byteswap and > > sort. > > >> The method situation could be made more consistent by swapping the > > >> boolean inplace flag in byteswapped with another 'out' argument and > > also > > >> having sort not operate in place by default, but also supply an out > > >> argument there. Thus: > > >> > > >> b = a.sort() # Returns a copy > > >> a.sort(out=a) # Sorts a in place > > >> a.sort(out=c) # Sorts a into c (probably just equivalent to c = > > a.sort() > > >> in this case since we don't want to rewrite the sort routines) > > >> > > > > > > Ugh. That's completely different semantics from sort() on lists, so I > > think > > > it would be a source of bugs (at least, it would mean keeping two > > different > > > ideas of .sort() in my head). > > > > > Thinking about it a bit more, I'd leave sort alone (returning None and > > all).. I was (over)reacting to changing to sort to return self, which > > makes the set of methods both less consistent within itself, less > > consistent with python and more error prone IMO, which seems the worst > > possibility. > > > Here is Guido on sort: > > I'd like to explain once more why I'm so adamant that * > sort*() shouldn't > *return* 'self'. > > This comes from a coding style (popular in various other languages, I > believe especially Lisp revels in it) where a series of side effects > > on a single object can be chained like this: > > x.compress().chop(y).*sort*(z) > > which would be the same as > > x.compress() > x.chop > (y) > x.*sort*(z) > > I find the chaining form a threat to readability; it requires that the > reader must be intimately familiar with each of the methods. The > > second form makes it clear that each of these calls acts on the same > object, and so even if you don't know the class and its methods very > well, you can understand that the second and third call are applied to > > x (and that all calls are made for their side-effects), and not to > something else. > > I'd like to reserve chaining for operations that *return* new values, > > like string processing operations: > > y = x.rstrip("\n").split(":").lower() > > There are a few standard library modules that encourage chaining of > side-effect calls (pstat comes to mind). There shouldn't be any new > > ones; pstat slipped through my filter when it was weak. > > So it seems you are correct in light of the Python philosophy. For those > operators that allow specification of out I would still like to see a > special value that means inplace, I think it would make the code clearer. Of > course, merely having the out flag violates Guido's intent. The idea seems > to be that we want some way to avoid allocating new memory. So maybe > byteswap should be inplace and return None, while a copyto method could be > added. Then one would do > > a.copyto(b) > b.byteswap() > > instead of > > b = a.byteswap() > > To expand on this a bit. Guidos philosophy, combined with a desire for memory efficiency, means that methods like byteswap and clip, which use the same memory, should operate inplace and return None. Thus, instead of b = a.clip(...) use b = a.copy() b.clip(...) Hey, it's a risc machine. If we did this, then functions could always return copies: b = clip(a,...) Chuck |