Mailing List Archive

I'd like list.pop to accept an optional second argument giving a default value
I like the list pop method because it provides a way to use
lists as thread safe queues and stacks (since append and pop
are protected by the global interpreter lock).

With pop, you can essentially test whether the list is
empty and get a value if it isn't in one atomic operation:

try:
foo=queue.pop(0)
except IndexError:
... empty queue case
else:
... non-empty case, do something with foo

Unfortunately, this incurs exception overhead. I'd rather do
something like:

foo=queue.pop(0,marker)
if foo is marker:
... empty queue case
else:
... non-empty case, do something with foo

I'd be happy to provide a patch.

Jim

--
Jim Fulton mailto:jim@digicool.com Python Powered!
Technical Director (888) 344-4332 http://www.python.org
Digital Creations http://www.digicool.com http://www.zope.org

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission. Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.
Re: I'd like list.pop to accept an optional second argument giving a default value [ In reply to ]
Jim> I like the list pop method because it provides a way to use lists
Jim> as thread safe queues and stacks (since append and pop are
Jim> protected by the global interpreter lock).

The global interpreter lock is a property of the current implementation of
Python, not of the language itself. At one point in the past Greg Stein
created a set of patches that eliminated the lock. While it's perhaps
convenient to use now, it may not always exist. I'm not so sure that it
should be used as a motivator for changes to libraries in the standard
distribution.

Skip
Re: I'd like list.pop to accept an optional second [ In reply to ]
Gordon McMillan wrote:
>
> Then how do I get the old behavior?

Just pass 0 or 1 argument.

>(I've been known to do odd
> things - like change behavior based on the number of args - in
> extension modules, but this ain't an extension).

It *is* a built-in method. It will be handled just like
dictionaries handle the second argument to get.

Jim

--
Jim Fulton mailto:jim@digicool.com Python Powered!
Technical Director (888) 344-4332 http://www.python.org
Digital Creations http://www.digicool.com http://www.zope.org

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission. Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.
Re: I'd like list.pop to accept an optional second [ In reply to ]
Gordon McMillan wrote:
>
> Jim Fulton wrote:
>
> > Gordon McMillan wrote:
> > >
> > > Then how do I get the old behavior?
> >
> > Just pass 0 or 1 argument.
> >
> > >(I've been known to do odd
> > > things - like change behavior based on the number of args - in
> > > extension modules, but this ain't an extension).
> >
> > It *is* a built-in method. It will be handled just like
> > dictionaries handle the second argument to get.
>
> d.get(nonexistantkey) does not throw an exception, it returns None.

Oops, I'd forgotten that.

> If list.pop() does not throw an exception when list is empty, it's
> new behavior.
>
> Which are you asking for:
> breaking code that expects IndexError

No.

> Violating Pythonic expectations by, in effect, creating 2 methods
> list.pop(void)
> list.pop(default_return)

Yes, except that I disagree that this is non-pythonic.

Jim

--
Jim Fulton mailto:jim@digicool.com Python Powered!
Technical Director (888) 344-4332 http://www.python.org
Digital Creations http://www.digicool.com http://www.zope.org

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission. Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.
Re: I'd like list.pop to accept an optional second [ In reply to ]
Jim Fulton writes:

> With pop, you can essentially test whether the list is
> empty and get a value if it isn't in one atomic operation:
>
> try:
> foo=queue.pop(0)
> except IndexError:
> ... empty queue case
> else:
> ... non-empty case, do something with foo
>
> Unfortunately, this incurs exception overhead. I'd rather do
> something like:
>
> foo=queue.pop(0,marker)
> if foo is marker:
> ... empty queue case
> else:
> ... non-empty case, do something with foo

I'm assuming you're asking for the equivalent of:
def pop(self, default=None):
much like dict.get?

Then how do I get the old behavior? (I've been known to do odd
things - like change behavior based on the number of args - in
extension modules, but this ain't an extension).

- Gordon
Re: I'd like list.pop to accept an optional second [ In reply to ]
Jim Fulton wrote:

> Gordon McMillan wrote:
> >
> > Then how do I get the old behavior?
>
> Just pass 0 or 1 argument.
>
> >(I've been known to do odd
> > things - like change behavior based on the number of args - in
> > extension modules, but this ain't an extension).
>
> It *is* a built-in method. It will be handled just like
> dictionaries handle the second argument to get.

d.get(nonexistantkey) does not throw an exception, it returns None.

If list.pop() does not throw an exception when list is empty, it's
new behavior.

Which are you asking for:
breaking code that expects IndexError
Violating Pythonic expectations by, in effect, creating 2 methods
list.pop(void)
list.pop(default_return)

- Gordon
Re: I'd like list.pop to accept an optional second [ In reply to ]
Gordon McMillan wrote:
>
> Offhand I can't think of a built-in that can't be expressed in normal
> Python notation, where "optional" args are really defaulted args.

I can define the pop I want in Python as follows:

_marker=[]

class list:
...
def pop(index=-1, default=marker):
try: v=self[index]
except IndexError:
if default is not marker:
return default
if self: m='pop index out of range'
else: m='pop from empty list'
raise IndexError, m
del self[index]
return v

Although I'm not sure why the "pythonicity" of an
interface should depend on it's implementation.

Jim

--
Jim Fulton mailto:jim@digicool.com Python Powered!
Technical Director (888) 344-4332 http://www.python.org
Digital Creations http://www.digicool.com http://www.zope.org

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission. Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.
Re: I'd like list.pop to accept an optional second [ In reply to ]
BTW, a good precedent for what I want
is getattr.

getattr(None,'spam')

raises an error, but:

getattr(None,'spam',1)

returns 1

Jim

--
Jim Fulton mailto:jim@digicool.com Python Powered!
Technical Director (888) 344-4332 http://www.python.org
Digital Creations http://www.digicool.com http://www.zope.org

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission. Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.
Re: I'd like list.pop to accept an optional second [ In reply to ]
Jim Fulton wrote:
>
> Gordon McMillan wrote:
...
> > Violating Pythonic expectations by, in effect, creating 2 methods
> > list.pop(void)
> > list.pop(default_return)
>
> Yes, except that I disagree that this is non-pythonic.
>

I'll leave the final determination to Mr. Python, but I disagree.
Offhand I can't think of a built-in that can't be expressed in normal
Python notation, where "optional" args are really defaulted args.

Which would lead us to either a new list method, or redefining pop:

def pop(usedefault=0, default=None)

and making you use 2 args.

But maybe I've missed a precedent because I'm so used to it. (Hmm, I
guess string.split is a sort-of precedent, because the first default
arg behaves differently than anything you could pass in).

- Gordon
Re: I'd like list.pop to accept an optional second [ In reply to ]
Jim Fulton wrote:
>
> > Violating Pythonic expectations by, in effect, creating 2 methods
> > list.pop(void)
> > list.pop(default_return)
>
> Yes, except that I disagree that this is non-pythonic.

Wouldn't a generic builtin for these kinds of things be
better, e.g. a function returning a default value in case
an exception occurs... something like:

tryexcept(list.pop(), IndexError, default)

which returns default in case an IndexError occurs. Don't
think this would be much faster that the explicit try:...except:
though...

--
Marc-Andre Lemburg
______________________________________________________________________
Y2000: 162 days left
Business: http://www.lemburg.com/
Python Pages: http://www.lemburg.com/python/
Re: I'd like list.pop to accept an optional second [ In reply to ]
>>>>> "M" == M <mal@lemburg.com> writes:

M> Wouldn't a generic builtin for these kinds of things be
M> better, e.g. a function returning a default value in case
M> an exception occurs... something like:

M> tryexcept(list.pop(), IndexError, default)

M> which returns default in case an IndexError occurs. Don't think
M> this would be much faster that the explicit try:...except:
M> though...

Don't know if this would be better (or useful, etc.), but it could
possibly be faster than explicit try/except, because with try/except
you have to instantiate the exception object. Presumably tryexcept()
-- however it was spelled -- would catch the exception in C, thus
avoiding the overhead of exception object instantiation.

-Barry
Re: I'd like list.pop to accept an optional second [ In reply to ]
>>>>> "Gordo" == Gordon McMillan <gmcm@hypernet.com> writes:

Gordo> Which are you asking for: breaking code that expects
Gordo> IndexError Violating Pythonic expectations by, in effect,
Gordo> creating 2 methods
Gordo> list.pop(void)
Gordo> list.pop(default_return)

The docs /do/ say that list.pop() is experimental, so that probably
gives Guido all the out he'd need to change the semantics :). I
myself have yet to use list.pop() so I don't know how disasterous the
change in semantics would be to existing code.

-Barry
Re: I'd like list.pop to accept an optional second [ In reply to ]
>>>>> "JF" == Jim Fulton <jim@digicool.com> writes:

JF> BTW, a good precedent for what I want
JF> is getattr.

JF> getattr(None,'spam')

JF> raises an error, but:

JF> getattr(None,'spam',1)

JF> returns 1

Okay, how did this one sneak in, huh? I didn't even realize this had
been added to getattr()! CVS reveals it was added b/w 1.5.1 and
1.5.2a1, so maybe I just missed the checkin message.

Fred, the built-in-funcs doc needs updating:

http://www.python.org/doc/current/lib/built-in-funcs.html

FWIW, the CVS log message says this feature is experimental too. :)

-Barry
Re: I'd like list.pop to accept an optional second [ In reply to ]
"Barry A. Warsaw" wrote:
>
> >>>>> "JF" == Jim Fulton <jim@digicool.com> writes:
>
> JF> BTW, a good precedent for what I want
> JF> is getattr.
>
> JF> getattr(None,'spam')
>
> JF> raises an error, but:
>
> JF> getattr(None,'spam',1)
>
> JF> returns 1
>
> Okay, how did this one sneak in, huh?

I don't know. Someone told me about it. I find it
wildly useful.

> I didn't even realize this had
> been added to getattr()! CVS reveals it was added b/w 1.5.1 and
> 1.5.2a1, so maybe I just missed the checkin message.
>
> Fred, the built-in-funcs doc needs updating:
>
> http://www.python.org/doc/current/lib/built-in-funcs.html
>
> FWIW, the CVS log message says this feature is experimental too. :)

Eek! I want it to stay!

I also really like list.pop. :)

Jim

--
Jim Fulton mailto:jim@digicool.com Python Powered!
Technical Director (888) 344-4332 http://www.python.org
Digital Creations http://www.digicool.com http://www.zope.org

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission. Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.
Re: I'd like list.pop to accept an optional second [ In reply to ]
>>>>> "JF" == Jim Fulton <jim@digicool.com> writes:





Barry A. Warsaw writes:
> Fred, the built-in-funcs doc needs updating:


This is done in the CVS repository; thanks for pointing out the
oversight!

Do people realize that pop() already has an optional parameter?
That *is* in the docs:

http://www.python.org/docs/current/lib/typesseq-mutable.html

See note 4 below the table.


-Fred

--
Fred L. Drake, Jr. <fdrake@acm.org>
Corporation for National Research Initiatives
Re: I'd like list.pop to accept an optional second [ In reply to ]
>>>>> "JF" == Jim Fulton <jim@digicool.com> writes:

JF> I don't know. Someone told me about it. I find it
JF> wildly useful.

No kidding! :)
Re: I'd like list.pop to accept an optional second [ In reply to ]
Jim Fulton wrote:
>
> [getattr(obj,name[,default])]
> > Okay, how did this one sneak in, huh?
>
> I don't know. Someone told me about it. I find it
> wildly useful.

Me too... ;-)

> > I didn't even realize this had
> > been added to getattr()! CVS reveals it was added b/w 1.5.1 and
> > 1.5.2a1, so maybe I just missed the checkin message.

http://www.deja.com/getdoc.xp?AN=366635977

--
Marc-Andre Lemburg
______________________________________________________________________
Y2000: 162 days left
Business: http://www.lemburg.com/
Python Pages: http://www.lemburg.com/python/
Re: I'd like list.pop to accept an optional second [ In reply to ]
>>>>> "M" == M <mal@lemburg.com> writes:

M> http://www.deja.com/getdoc.xp?AN=366635977

Ah, thanks! Your rationale was exactly the reason why I added
dict.get(). I'm still not 100% sure about list.pop() though, since
it's not exactly equivalent -- list.pop() modifies the list as a
side-effect :) Makes me think you might want an alternative spelling
for list[s], call it list.get() and put the optional default on that
method. Then again, maybe list.pop() with an optional default is good
enough.

-Barry
Re: I'd like list.pop to accept an optional second [ In reply to ]
> > Fred, the built-in-funcs doc needs updating:
> >
> > http://www.python.org/doc/current/lib/built-in-funcs.html
> >
> > FWIW, the CVS log message says this feature is experimental too. :)
>
> Eek! I want it to stay!
>
> I also really like list.pop. :)

Seconded!

Also, things which appeared between some alphas and made
it upto the final, are just there.

It would be fair to update the CVS tree and say the features
made it into the dist, even if it just was a mistake
not to remove them in time. It was time enough.

ciao - chris

--
Christian Tismer :^) <mailto:tismer@appliedbiometrics.com>
Applied Biometrics GmbH : Have a break! Take a ride on Python's
Kaiserin-Augusta-Allee 101 : *Starship* http://starship.python.net
10553 Berlin : PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint E182 71C7 1A9D 66E9 9D15 D3CC D4D7 93E2 1FAE F6DF
we're tired of banana software - shipped green, ripens at home
Re: I'd like list.pop to accept an optional second [ In reply to ]
"Barry A. Warsaw" wrote:
>
> >>>>> "M" == M <mal@lemburg.com> writes:
>
> M> http://www.deja.com/getdoc.xp?AN=366635977
>
> Ah, thanks! Your rationale was exactly the reason why I added
> dict.get(). I'm still not 100% sure about list.pop() though, since
> it's not exactly equivalent -- list.pop() modifies the list as a
> side-effect :) Makes me think you might want an alternative spelling
> for list[s], call it list.get() and put the optional default on that
> method. Then again, maybe list.pop() with an optional default is good
> enough.

list.get and list.pop are different, since get wouldn't modify the list
and pop would.

Jim


--
Jim Fulton mailto:jim@digicool.com Python Powered!
Technical Director (888) 344-4332 http://www.python.org
Digital Creations http://www.digicool.com http://www.zope.org

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission. Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.
Re: I'd like list.pop to accept an optional second [ In reply to ]
>>>>> "JF" == Jim Fulton <jim@digicool.com> writes:

JF> list.get and list.pop are different, since get wouldn't modify
JF> the list and pop would.

Right. Would we need them both?
Re: I'd like list.pop to accept an optional second [ In reply to ]
"Barry A. Warsaw" wrote:
>
> >>>>> "JF" == Jim Fulton <jim@digicool.com> writes:
>
> JF> list.get and list.pop are different, since get wouldn't modify
> JF> the list and pop would.
>
> Right. Would we need them both?

Sure. Since a sequence is sort of a special kind of mapping,
get makes sense.

I definately, want pop.

Jim

--
Jim Fulton mailto:jim@digicool.com Python Powered!
Technical Director (888) 344-4332 http://www.python.org
Digital Creations http://www.digicool.com http://www.zope.org

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission. Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.
RE: I'd like list.pop to accept an optional second [ In reply to ]
[M.-A. Lemburg]
> Wouldn't a generic builtin for these kinds of things be
> better, e.g. a function returning a default value in case
> an exception occurs... something like:
>
> tryexcept(list.pop(), IndexError, default)
>
> which returns default in case an IndexError occurs. Don't
> think this would be much faster that the explicit try:...except:
> though...

As a function (builtin or not), tryexcept will never get called if
list.pop() raises an exception. tryexcept would need to be a new statement
type, and the compiler would have to generate code akin to

try:
whatever = list.pop()
except IndexError:
whatever = default

If you want to do it in a C function instead to avoid the Python-level
exception overhead, the compiler would have to wrap list.pop() in a lambda
in order to delay evaluation until the C code got control; and then you've
got worse overhead <wink>.

generalization-is-the-devil's-playground-ly y'rs - tim
RE: I'd like list.pop to accept an optional second [ In reply to ]
[Barry]
> FWIW, the CVS log message says this feature [3-arg getattr] is
> experimental too. :)

[Jim]
> Eek! I want it to stay!
>
> I also really like list.pop. :)

Don't panic: Guido has never removed a feature explicitly called
"experimental"; he's only removed non-experimental ones.

that's-why-we-call-stackless-python-"an-experiment"<wink>-ly y'rs - tim
RE: I'd like list.pop to accept an optional second argument giving a defaultvalue [ In reply to ]
In a moment of insanity, Guido gave me carte blanche to suggest new list
methods, and list.pop & list.extend were the result. I considered spec'ing
list.pop to take an optional "default on bad index" argument too, but after
playing with it didn't like it (always appeared just as easy & clearer to
use "if list:" / "while list:" etc).

Jim has a novel use I hadn't considered:

> With pop, you can essentially test whether the list is
> empty and get a value if it isn't in one atomic operation:
>
> try:
> foo=queue.pop(0)
> except IndexError:
> ... empty queue case
> else:
> ... non-empty case, do something with foo
>
> Unfortunately, this incurs exception overhead. I'd rather do
> something like:
>
> foo=queue.pop(0,marker)
> if foo is marker:
> ... empty queue case
> else:
> ... non-empty case, do something with foo

It's both clever and pretty. OTOH, the original try/except isn't expensive
unless the "except" triggers frequently, in which case (the queue is often
empty) a thread is likely better off with a yielding Queue.get() call.

So this strikes me as useful only for thread micro-optimization, and a kind
of optimization most users should be steered away from anyway. Does anyone
have a real use for this outside of threads? If not, I'd rather it not go
in.

For threads that need an optimized non-blocking probe, I'd write it:

gotone = 0
if queue:
try:
foo = queue.pop(0)
gotone = 1
except IndexError:
pass
if gotone:
# use foo
else:
# twiddle thumbs

For the IndexError to trigger there, a thread has to lose its bytecode slice
between a successful "if queue" and the queue.pop, and not get another
chance to run until other threads have emptied the queue.

1 2  View All