Question about idioms for clearing a list

B

bonono

Magnus said:
... add=list.append
... def clear(self):
... del self[:]
...
b = BryansList([1,2,3,4,5])
b [1, 2, 3, 4, 5]
b.add(6)
b.clear()
b
[]

Happy now? You can keep it, I don't need it. :)
Most of us consider minimal interfaces a virtue.

What kind of performance penalty are we talking about here ? list being
such a fundamental thing, no one would like to use a slower version
just for the clear/add method. And if it is a "use when you really need
to", it would make the code harder to understand as it would be
"sometimes it is BryansList, sometimes it is builtin list".

That said, I don't find clear() to be useful as unless one needs to
pass around a single copy of list object around and saved them for
future use(which can be a source of subtle bug), just lst=[] is usually
good enough for localized usage.
 
B

Bryan Olson

Magnus said:
I don't understand the second one. Where did 't' come from?

Cut-and-past carelessness. Meant to update with 'collection'.
Anyway, tiny code snippets are hardly usecases.

The task is the usecase.

[...]
I still don't see any convincing usecase for the kind of
ducktyping you imply.

I didn't say I could convince you. I said that when different
types can support the same operation, they should also support
the same interface. That's what enables polymorphism.
 
R

Raymond Hettinger

If you're asking why list's don't have a clear() method, the answer is
that they already had two ways to do it (slice assignment and slice
deletion) and Guido must have valued API compactness over collection
polymorphism. The latter is also evidenced by set.add() vs
list.append() and by the two pop() methods having a different
signatures.
[bonono]
Sounds to me that it is a preference(style, whatever), rather than some
other posts of this thread argued that "del L[:]" is better.

It was simply design decision reflecting Guido's values on language
economics.

If you're asking why your specific case looked so painful, I suspect
that it only looked hard because the adaptation was force-fit into a
lambda (the del-statement or slice assignment won't work as an
expression). You would have had similar difficulties embedding
try/except logic or a print-statement. Guido, would of course
recommend using a plain def-statement:

L = list()
def L_clearer(L=L):
del L[:]
for listbunch in buncher(src, '', L, L.append, L_clearer):
print listbunch
Is that really "clearer" ? While it is still very localized(just read a
few lines up for the definition), buncher(src, '', L.append, L.clear)
seems to be clearer to me, especially there are two similar construct
on set/dict above,

Hmm, my post was so long that the main points were lost:

* the example was tricky only because of the unnecessary in-place
update requirement

* eliminating that requirement solves the adaptation problem and
simplifies the client code

* the constructor API is polymorphic, use it

* adding clear() doesn't help with the other API variations between
set, list, dict, etc.

* Guido's decision for distinct APIs is intentional (i.e. set.add vs
list.append)

* Alex's adapter PEP is likely a better solution for forcing
polymorphism on unlike APIs

* When a lambda becomes awkward, Guido recommends a separate def

* Guido has no sympathy for atrocities resulting from squeezing
everything into one line

* Alex's example can be simplified considerably:

def buncher(sourceit, sentinel, constructor):
for k, g in groupby(sourceit, lambda x: x != sentinel):
if k:
yield constructor(g)

for setbunch in buncher(src, '', set):
print setbunch

* The improved version has no need for list.clear(). End of story.


Raymond
 
B

Bryan Olson

Raymond Hettinger wrote:
[...]
If you're asking why list's don't have a clear() method, the answer is
that they already had two ways to do it (slice assignment and slice
deletion) and Guido must have valued API compactness over collection
polymorphism.

That's a decision from long ago. Now that we have sets and
the iterable protocol, the case is quite different.
 
M

Magnus Lycka

Bryan said:
Cut-and-past carelessness. Meant to update with 'collection'.

If some_iter gives you dicts, the code above will throw away
your values, and put the set of keys in big_union. Is that what
you meant to do? I suspect most people would find this somewhat
surprising. For sets and "BryanLists" it will put a set of all
the contents of those collections in big_union. I think this
just verifies my previous arguments. It's rarely meaningful to
write functions that are meaingful for all builtin collections.
 
B

Bryan Olson

Magnus said:
If some_iter gives you dicts, the code above will throw away
your values, and put the set of keys in big_union. Is that what
you meant to do?

It can be quite useful. Python only recently added the set
type. Previously, the usual way to implement sets with
efficient membership testing was to use a dict where the
keys map to some irrelevant value. The above will work for
the old technique as well as for the set type.

> I suspect most people would find this somewhat
surprising. For sets and "BryanLists" it will put a set of all
the contents of those collections in big_union.

That was the description: moving everything from several
collections into a single union.

I think this
just verifies my previous arguments. It's rarely meaningful to
write functions that are meaingful for all builtin collections.

That's a nonsense argument, polymorphism doesn't have to work
over every type to be useful. Functions meaningful for either
sets or lists are common; that's enough justification for
giving corresponding operations the same interface.
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,008
Latest member
Rahul737

Latest Threads

Top