Pythonic way for missing dict keys

  • Thread starter Bruno Desthuilliers
  • Start date
S

Steve Holden

Alex said:
Alex Popescu said:
@x40g2000prg.googlegroups.com:

On Jul 21, 7:48 am, Duncan Booth <[email protected]>
wrote:

[snip...]


From the 2.6 PEP #361 (looks like dict.has_key is deprecated)
Python 3.0 compatability: ['compatibility'-->someone should use a
spell-checker for 'official' releases]
- warnings were added for the following builtins which no
longer exist in 3.0:
apply, callable, coerce, dict.has_key, execfile,
reduce,
reload

I see... what that document doesn't describe is the alternatives to
be used. And I see in that list a couple of functions that are
probably used a lot nowadays (callable, reduce, etc.).
callable and reduce are rarely used, at least in code I've seen.

I thought G would be using that function a lot. Also, what is the
replacement of reduce? I think I remember seeing somewhere that lists
comprehension would be (but also remember the advise that reduce will be
quicker).
See his latest blog entry on artima.com, where he has started a Py3k
FAQ. He suggests that uses if reduce are almost always more readable
when written using a for loop and an accumulator variable.

http://www.artima.com/weblogs/viewpost.jsp?thread=211200
dict.has_key(key) becomes key in dict (correct?)


I think there were some advises to not use apply.
Yup. Anyway there's a trivial translation for uses of apply.

apply(f, *args, **kw) => f(*args, **kw)

The converter will almost certainly do this for you.
I don't ever remember using execfile. It has always been a blot on the
landscape.
What is the replacement for this one?
I'd have to guess, and will refrain from doing so.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://del.icio.us/steve.holden
--------------- Asciimercial ------------------
Get on the web: Blog, lens and tag the Internet
Many services currently offer free registration
----------- Thank You for Reading -------------
 
S

Steven D'Aprano

Alex Popescu said:
@x40g2000prg.googlegroups.com:

On Jul 21, 7:48 am, Duncan Booth <[email protected]>
wrote:

[snip...]


From the 2.6 PEP #361 (looks like dict.has_key is deprecated)
Python 3.0 compatability: ['compatibility'-->someone should use a
spell-checker for 'official' releases]
- warnings were added for the following builtins which no
longer exist in 3.0:
apply, callable, coerce, dict.has_key, execfile,
reduce,
reload


I see... what that document doesn't describe is the alternatives to
be used. And I see in that list a couple of functions that are
probably used a lot nowadays (callable, reduce, etc.).

callable and reduce are rarely used, at least in code I've seen.

I thought G would be using that function a lot.

Who or what is G? Guido?

And which of the two functions mentioned is "that function"? callable()?


Instead of doing:


if callable(function): function()

you should do:

try:
function()
except TypeError:
pass


That should work for most uses of callable(), but isn't quite the same.
(What if function() has side-effects, or is expensive, and you want to
determine if it is callable, but not actually call it _now_?)

Also, what is the replacement of reduce? I think I remember seeing
somewhere that lists comprehension would be (but also remember the
advise that reduce will be quicker).

No, a list comprehension isn't equivalent to reduce(). There is no
replacement for reduce().

Guido has essentially done the functional equivalent of deciding that
because he personally doesn't like for loops, they can and should be
written out as:

counter = 0
while counter < len(sequence):
item = sequence[counter]
do_something_with_item
counter += 1

because it is "easier to read" than a for loop.

And yes, if you think my example is extreme because nobody would be that
stupid, that's the point: removing reduce() _is_ that stupid (and it is
not often I say that about a language design decision by Guido!). Python
can, and probably will, get away with it only because reducing an iterable
to a single value is an uncommon operation, and the most common uses of it
(summing a sequence, finding the minimum and maximum) already have
workable replacements.

It's especially stupid because map() and filter(), both of which do have
simple, easy to understand, completely functional replacements, are going
to stay. reduce() doesn't, and it is going. That's nuts.

It's a shame really. Oh well, maybe it will sneak back in via a functional
module, or itertools, or something. What a waste, what a waste.

dict.has_key(key) becomes key in dict (correct?)
Yes.




I think there were some advises to not use apply.


help(apply) already tells you how to replace apply():

Deprecated since release 2.3. Instead, use the extended call syntax:
function(*args, **keywords).


What is the replacement for this one?


Slurp the file into a string, execute the string.


But the thing that makes my brain melt is reload(). No, reload() probably
isn't good enough to use in production code, but for interactive use it is
Good Enough. I'm boggled that it is going away!
 
D

Duncan Booth

Steven D'Aprano said:
Instead of doing:


if callable(function): function()

you should do:

try:
function()
except TypeError:
pass


That should work for most uses of callable(), but isn't quite the
same. (What if function() has side-effects, or is expensive, and you
want to determine if it is callable, but not actually call it _now_?)

The replacement for callable(x) is simply hasattr(x, '__call__').
Once upon a time it may have been that functions didn't have a __call__
attribute (I haven't checked back on really old Pythons top see if this
was the case), but these
No, a list comprehension isn't equivalent to reduce(). There is no
replacement for reduce().
<snip>
There are of course several replacements for specialised uses of reduce:
sum, any, all. There is no general purpose replacement, but you can
write one in a few lines if you really need it.
It's a shame really. Oh well, maybe it will sneak back in via a
functional module, or itertools, or something. What a waste, what a
waste.

I'm sure it will reappear in some other module, but that's the correct
place for a little used function, not in builtins.
 
S

Steven D'Aprano

The replacement for callable(x) is simply hasattr(x, '__call__').
Once upon a time it may have been that functions didn't have a __call__
attribute (I haven't checked back on really old Pythons top see if this
was the case), but these

Your sentence seems to have run out early :)

Thanks, I didn't know that -- I remember that Back In The Day checking if
something was callable was tricky, because it could be a function, a
method, or a class with __call__. It makes much more sense to make all
callables go through __call__.


<snip>
There are of course several replacements for specialised uses of reduce:
sum, any, all. There is no general purpose replacement, but you can
write one in a few lines if you really need it.

True. But writing the same basic algorithm over and over again is about as
far from best practice as you can get without being a PHP programmer.
*wink* Currying is easy to do too, but Python has grown a function
functools.partial() to do it properly. That's as it should be.

(Yes, I know that's a misuse of the term currying, but it's a common one,
and easier than saying "Making a partial function".)

I'm sure it will reappear in some other module, but that's the correct
place for a little used function, not in builtins.

Oh, I would have no problem at all with reduce being banished to the
functtools module. But it's a shame to have to go through the whole PEP
process, and risk Guido saying no.
 
J

John J. Lee

Steve Holden said:
Yup. Anyway there's a trivial translation for uses of apply.

apply(f, *args, **kw) => f(*args, **kw)
[...]

Steve means:

apply(f, args, kw) => f(*args, **kw)


John
 
C

Chris Mellon

@x40g2000prg.googlegroups.com:

On Jul 21, 7:48 am, Duncan Booth <[email protected]>
wrote:

[snip...]


From the 2.6 PEP #361 (looks like dict.has_key is deprecated)
Python 3.0 compatability: ['compatibility'-->someone should use a
spell-checker for 'official' releases]
- warnings were added for the following builtins which no
longer exist in 3.0:
apply, callable, coerce, dict.has_key, execfile,
reduce,
reload


I see... what that document doesn't describe is the alternatives to
be used. And I see in that list a couple of functions that are
probably used a lot nowadays (callable, reduce, etc.).

callable and reduce are rarely used, at least in code I've seen.

I thought G would be using that function a lot.

Who or what is G? Guido?

And which of the two functions mentioned is "that function"? callable()?


Instead of doing:


if callable(function): function()

you should do:

try:
function()
except TypeError:
pass


That should work for most uses of callable(), but isn't quite the same.
(What if function() has side-effects, or is expensive, and you want to
determine if it is callable, but not actually call it _now_?)

It's *really* not the same. Not only does it call the function, which
has all kinds of potential problems like you listed, but this also
will convert TypeErrors in the called function into "this is not a
callable", which is almost certainly not what you want. hasattr(x,
'__call__') works but is annoying to write and hides intent. I'd be
happy if inspect grew iscallable.
 
B

Bruno Desthuilliers

John J. Lee a écrit :
@x40g2000prg.googlegroups.com:

[snip...]


From the 2.6 PEP #361 (looks like dict.has_key is deprecated)
Python 3.0 compatability: ['compatibility'-->someone should use a
spell-checker for 'official' releases]
- warnings were added for the following builtins which no
longer exist in 3.0:
apply, callable, coerce, dict.has_key, execfile, reduce,
reload

I see... what that document doesn't describe is the alternatives to be
used. And I see in that list a couple of functions that are probably used a
lot nowadays (callable, reduce, etc.).


callable and reduce are rarely used, at least in code I've seen.

I do use callable(). Not everyday, for sure, but still often enough to
have to reimplement it when I'll switch to Py3K.

And while I rarely use it, I'll regret reduce().
I
would agree there will be a large number of programs that contain one
or two calls to these functions, though. Certainly has_key will be
the most common of those listed above (but trivial to fix). apply
will be common in old code from the time of Python 1.5.2.

I still use it (in a somewhat deviant way) to define properties:

class MyClass(object):
def __init__(self, val):
self.val = val
@apply
def val():
def fget(self):
return self._val
def fset(self, val):
self._val = val

execfile is
perhaps more common that callable (?)

Never used it, never saw it used.
 
B

Bruno Desthuilliers

Steven D'Aprano a écrit :
(snip)
Instead of doing:


if callable(function): function()

you should do:

try:
function()
except TypeError:
pass

There are time where you may want to know if you have a callable without
calling it...
That should work for most uses of callable(), but isn't quite the same.
(What if function() has side-effects, or is expensive, and you want to
determine if it is callable, but not actually call it _now_?)

Indeed.

The 'correct' replacement would be:

if hasattr(obj, '__call__'):
# it's a callable

but I don't find it so Pythonic to have to check for a __magic__ method.

Also, what is the replacement of reduce? I think I remember seeing
somewhere that lists comprehension would be (but also remember the
advise that reduce will be quicker).


No, a list comprehension isn't equivalent to reduce(). There is no
replacement for reduce().

Guido has essentially done the functional equivalent of deciding that
because he personally doesn't like for loops, they can and should be
written out as:

counter = 0
while counter < len(sequence):
item = sequence[counter]
do_something_with_item
counter += 1

because it is "easier to read" than a for loop.

And yes, if you think my example is extreme because nobody would be that
stupid, that's the point: removing reduce() _is_ that stupid (and it is
not often I say that about a language design decision by Guido!). Python
can, and probably will, get away with it only because reducing an iterable
to a single value is an uncommon operation, and the most common uses of it
(summing a sequence, finding the minimum and maximum) already have
workable replacements.

It's especially stupid because map() and filter(), both of which do have
simple, easy to understand, completely functional replacements, are going
to stay. reduce() doesn't, and it is going. That's nuts.

InMyArms(TM) !

(Guido, if you read us...)
 
A

Alex Popescu

Steven D'Aprano a écrit :
(snip)



There are time where you may want to know if you have a callable
without calling it...


Indeed.

The 'correct' replacement would be:

if hasattr(obj, '__call__'):
# it's a callable

but I don't find it so Pythonic to have to check for a __magic__
method.

It looks like Python devs have decided it is Pythonic, because it is
already in the PEP. Same for execfile and the others. And I am not
arguing pro or con. I was just wondering about the reasons, as I haven't
been able to find anything (neither here nor on the dev group).

bests,
../alex
 
B

Bruno Desthuilliers

Alex Popescu a écrit :
It looks like Python devs have decided it is Pythonic, because it is
already in the PEP.

I do know, and I disagree with this decision.

FWIW, repr(obj) is mostly syntactic sugar for obj.__repr__(),
getattr(obj, name) for obj.__getattr__(name), type(obj) for
obj.__class__ etc... IOW, we do have a lot of builtin functions that
mostly encapsulate calls to __magic__ methods, and I definitively don't
understand why this specific one (=> callable(obj)) should disappear. I
usually have lot of respect for Guido's talent as a language designer
(obviously since Python is still MFL), but I have to say I find this
particular decision just plain stupid. Sorry.
 
A

Alex Martelli

Alex Popescu a écrit :

I do know, and I disagree with this decision.

FWIW, repr(obj) is mostly syntactic sugar for obj.__repr__(),
getattr(obj, name) for obj.__getattr__(name), type(obj) for
obj.__class__ etc... IOW, we do have a lot of builtin functions that
mostly encapsulate calls to __magic__ methods, and I definitively don't
understand why this specific one (=> callable(obj)) should disappear. I

Maybe because it DOESN'T "encapsulate a call" to a magic method, but
rather the mere check for the presence of one?
usually have lot of respect for Guido's talent as a language designer
(obviously since Python is still MFL), but I have to say I find this
particular decision just plain stupid. Sorry.

The mere check of whether an object possesses some important special
method is best accomplished through the abstract-base-classes machinery
(new in Python 3.0: see <http://www.python.org/dev/peps/pep-3119/>). At
this time there is no Callable ABC, but you're welcome to argue for it
on the python-3000 mailing list (please do check the archives and/or
check privately with the PEP owner first to avoid duplication).


Alex
 
B

Bruno Desthuilliers

Alex Martelli a écrit :
Maybe because it DOESN'T "encapsulate a call" to a magic method, but
rather the mere check for the presence of one?

Yes, true. But it doesn't make such a big difference IMHO : it's about
decoupling API (the builtin funcs) from implementation (accessing |
calling | checking for the presence of a given implementation attribute).
The mere check of whether an object possesses some important special
method is best accomplished through the abstract-base-classes machinery
(new in Python 3.0: see <http://www.python.org/dev/peps/pep-3119/>). At
this time there is no Callable ABC, but you're welcome to argue for it
on the python-3000 mailing list (please do check the archives and/or
check privately with the PEP owner first to avoid duplication).

I'll have a look. Thanks for the pointers.
 
A

Alex Popescu

(e-mail address removed) (Alex Martelli) wrote in (e-mail address removed):
Alex Popescu a écrit :

[... snip ...]


The mere check of whether an object possesses some important special
method is best accomplished through the abstract-base-classes machinery
(new in Python 3.0: see <http://www.python.org/dev/peps/pep-3119/>). At
this time there is no Callable ABC, but you're welcome to argue for it
on the python-3000 mailing list (please do check the archives and/or
check privately with the PEP owner first to avoid duplication).

This PEP sounds very similar to Java interfaces (well, as an enhanced
version as you are allowed to programmatically control this inheritance
chain). Interesting approach. And now I can agree that the removal of
callable() makes sense!

Thanks a lot for the pointer Alex.

../alex
 

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

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,163
Latest member
Sasha15427
Top