LangWart: Method congestion from mutate multiplicty

Steven D'Aprano steve+comp.lang.python at pearwood.info
Sun Feb 10 19:36:20 EST 2013


Rick Johnson wrote:

> On Sunday, February 10, 2013 5:29:54 AM UTC-6, Steven D'Aprano wrote:
>> Rick wrote:
>> And you have missed my point, which is that reversed(), and sorted(),
>> were not added to the language on a whim, but because they were
>> requested, over and over and over again.
> 
> Well, well, this explains everything!
> 
> We don't add features because of logic, or because of consistency, or even
> because of good sense, we simply add them to appease the masses.

They were requested because people kept re-inventing them. They kept
re-inventing them because they are useful functions that make good sense to
have.


>> "appended" is called list addition.
>>
>> newlist = oldlist + [item_to_append]
> 
> But where is the consistency?

Strings use + for concatenation. Tuples use + for concatenation. Lists use +
for concatenation. Seems pretty consistent to me.

Are you sure you've used Python before?


> Yes the syntactic sugar of the "plus sign" is concise, however, the "+"
> operator does not "pair" intuitively with the "append" method. 

Adding "ed" to a word does not pair intuitively with the method name. You
have to learn it, which in the case of most English speakers you probably
did between the ages of 2 and 6.

Using + to represent concatenation is no less intuitive.



> Even IF you 
> transformed the "+" operator into a named method like "add" (or call the
> magic method "__add__") it still fails to mesh properly with "append", and
> the two words utterly fail to intuitively establish an "in-place" versus
> "copy-mutate" relationship. 

So what?



>> >  flatten, flattened
>> 
>> flatten is another often requested, hard to implement correctly,
>> function. The only reason that Python doesn't have a flatten is that
>> nobody can agree on precisely what it should do.
> 
> Steven, the definition of flatten (as relates to sequences) is very, VERY
> simple:
> 
>     Return a new sequence that is the result of reducing
>     a nested sequence of sequences into a single depth
>     sequence.

Very, VERY simple until you actually implement this function, and discover
that it does too much e.g.

flatten([None, 23, [1, 2, 3], Point(x=2, y=3), ["spam", "ham"]])

=> [None, 23, 1, 2, 3, 2, 3, 's', 'p', 'a', 'm', 'h', 'a', 'm']


So people who have *actually programmed*, instead of just talking about
programming, have discovered that in practice you need to treat some
sequences as primitives that don't get expanded.



>> Like map, filter, reduce, etc. flatten is not sensibly implemented as a
>> mutator method, but as a function.
> 
> Only because you, along with a few other high ranking members of this
> community (including the BDFL himself!) have this /aversion/ to true OOP
> paradigm.
> 
> Can you provide an example of how flatten "as a method" is incorrect
> versus flatten "as a function" is correct, or will this challenge be
> silently swept under the rug as so many before?

Simple efficiency. The most efficient, and sensible, way to flatten a list
is to create a new list. Trying to flatten a list in place is a dumb
idea -- it is O(n**2), or possibly even worse. Since only an idiot would
write flatten as an in-place method, any mutator version of flatten would
have to use a non-mutator version, then use slicing to over-write itself:

def flatten(self):
    new_list = flatten(self)
    self[:] = new_list


which is fine if you absolutely have to have an in-place version, but why
bother? The caller can do it themselves:

mylist = flatten(mylist)


[snip]
>> >  map, mapped
>> >  filter, filtered
>> >  reduce, reduced
>> 
>> Those are nonsense. None of those are in-place mutator methods.
> 
> Well not in the current implementation of Python; but they could be if we
> wanted them to be.

Now you're smoking crack. How can *reduce* be an in-place mutator method?

py> mylist = [1, 2, 3, 4, 5]
py> from operator import mul
py> reduce(mul, mylist)
120

I would really like to see your implementation of a reduce method that turns
a list into an int *in-place*.



> Applying mutations both "in-place" and "to a copy" are 
> very helpful.

Exactly.


[snip]
>> > My point was this: All mutate methods should mutate "in-place",
>> 
>> Well duh. All mutator methods do mutate in-place, otherwise they wouldn't
>> be mutator methods.
> 
> So "reversed()" and "sorted()" mutate in-place?

No. They are not mutator methods, because they do not mutate in place.


>> > if the
>> > programmer wishes to create a mutated copy of the object, then the
>> > programmer should /explicitly/ create a copy of the object and then
>> > apply the correct mutator method to the copy.
>> 
>> Been there, done that, it sucks. That's about a dozen steps backwards to
>> a worse time in Python development.
> 
> Why? Because you have to type this
> 
>     reversed = list(seq).reverse()

Are you sure you've programmed in Python before? That gives reversed = None.


-- 
Steven




More information about the Python-list mailing list