short path evaluation, why is f() called here: dict(a=1).get('a',f())

A

aspineux

This append in both case

dict(a=1).get('a', f())
dict(a=1).setdefault('a', f())

This should be nice if f() was called only if required.

Regards.
 
C

Chris Mellon

This append in both case

dict(a=1).get('a', f())
dict(a=1).setdefault('a', f())

This should be nice if f() was called only if required.

Think about the change to Python semantics that would be required for
this to be true, and then use collections.defaultdict instead.
 
N

Neil Cerutti

This append in both case

dict(a=1).get('a', f())
dict(a=1).setdefault('a', f())

This should be nice if f() was called only if required.

Shortcomings of those methods is probably why collections.defaultdict
is so popular.
.... return 7
....
d = defaultdict(f, a=1)
d['a'] 1
d['b']
7

get and setdefault aren't needed when using a default dict, and the
default factory is called only when needed.
 
A

aspineux

Think about the change to Python semantics that would be required for
this to be true, and then use collections.defaultdict instead.

Yes, I missed 'get' and 'setdefault' are functions :)
Then why not some new semantic

d.get('a', f()) --> d['a', f()]
d.setdefault('a', f()) --> d['a'=f()]

Is is a good idea enough to change the python semantic ?
Or simply is it a good idea ?
 
P

Paul Rubin

aspineux said:
Yes, I missed 'get' and 'setdefault' are functions :)
Then why not some new semantic

d.get('a', f()) --> d['a', f()]
d.setdefault('a', f()) --> d['a'=f()]

Is is a good idea enough to change the python semantic ?
Or simply is it a good idea ?

Changing python semantics for something like this is nuts. Allowing
passing a callable (sort of like re.sub allows) makes a certain
amount of sense:

d.get('a', default=f)

You can also write (python 2.5, untested):

d['a'] if 'a' in d else f()
 
S

Steven D'Aprano

aspineux said:
Yes, I missed 'get' and 'setdefault' are functions :) Then why not
some new semantic

d.get('a', f()) --> d['a', f()]
d.setdefault('a', f()) --> d['a'=f()]

Is is a good idea enough to change the python semantic ? Or simply is
it a good idea ?

Changing python semantics for something like this is nuts. Allowing
passing a callable (sort of like re.sub allows) makes a certain amount
of sense:

d.get('a', default=f)


But how can Python determine when you want the result to be *the
callable* and when you want it to be *the result of calling the
callable*?

Functions and other callables are first-class objects, and it is quite
reasonable to have something like this:

map = {'a': Aclass, 'b': Bclass, 'c': Cclass}
class_ = map.get(astring, default=Zclass)

The result I want is the class, not the result of calling the class
(which would be an instance). If I wanted the other semantics, I'd be
using defaultdict instead.
 
T

Tim Chase

But how can Python determine when you want the result to be *the
callable* and when you want it to be *the result of calling the
callable*?

Functions and other callables are first-class objects, and it is quite
reasonable to have something like this:

map = {'a': Aclass, 'b': Bclass, 'c': Cclass}
class_ = map.get(astring, default=Zclass)

The result I want is the class, not the result of calling the class
(which would be an instance). If I wanted the other semantics, I'd be
using defaultdict instead.

For an example of the defaultdict usage without calling it the
first time:

from collections import defaultdict
def f():
print "Doing some expensive calculation"
return 42

d = defaultdict(f)
d['hello'] = 3.14159
print 'Hello:', d['hello']
print 'World:', d['world']
print 'World (again):', d['world']

This results in the expensive calculation only being executed
once and having the result stored in the defaultdict. This is a
good thing.

If you're doing as Steven suggests, you can pass and store
function objects or class objects with the same ease:
map = {'a': Aclass, 'b': Bclass, 'c': Cclass}
class_ = map.get(astring, default=Zclass)

Other than tromping on the "map" built-in, one can then
instantiate the given class with

my_instance = map.get(astring, default=Zclass)(params)

Perfect for the factory pattern if you groove on that sort of thing.

-tkc
 
P

Paul Rubin

Steven D'Aprano said:
map = {'a': Aclass, 'b': Bclass, 'c': Cclass}
class_ = map.get(astring, default=Zclass)

The result I want is the class, not the result of calling the class
(which would be an instance). If I wanted the other semantics, I'd be
using defaultdict instead.

I used default as a keyward arg name indicating the presence of
a callable. I probably should have called it defaultfunc or something.

x = d.get('a', f) # --> default value is f
x = d.get('a', defaultfunc=f) # --> default value is result of f() .
 
S

Steven D'Aprano

I used default as a keyward arg name indicating the presence of a
callable. I probably should have called it defaultfunc or something.

x = d.get('a', f) # --> default value is f x = d.get('a',
defaultfunc=f) # --> default value is result of f() .


So you're talking about proposed *added* behaviour, rather than
*replacing* the current behaviour?

Sorry if I misunderstood you in the first place.
 
A

aspineux

I used default as a keyward arg name indicating the presence of
a callable. I probably should have called it defaultfunc or something.

x = d.get('a', f) # --> default value is f
x = d.get('a', defaultfunc=f) # --> default value is result of f() .

Nice idea, but if I want args I need to write it like that:

x=d.get('a', defaultfunc=f, funcargs=(1,2,3))

instead of d['a', f(1,2,3)]
 
A

aspineux

Think about the change to Python semantics that would be required for
this to be true, and then use collections.defaultdict instead.

Yes, I missed 'get' and 'setdefault' are functions :)
Then why not some new semantic

d.get('a', f()) --> d['a', f()]
d.setdefault('a', f()) --> d['a'=f()]

Is is a good idea enough to change the python semantic ?
Or simply is it a good idea ?

Thanks for all your answers.

Anyway these notations are very compact,
don't require the definition of a specific function,
and work with old style/or already existing dictionary,
dictionary you didn't created yourself.

While the use of defaultdict require the definition of such a function
and to control the creation of the dictionary.

For me the best alternative that match the requirement above is
the one provided by Paul Rubin.


Regards.
 
P

Paul Rubin

aspineux said:
Nice idea, but if I want args I need to write it like that:

x=d.get('a', defaultfunc=f, funcargs=(1,2,3))

Yeah, that looks good. The default arg to f should be the key being
looked up.
 

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
474,444
Messages
2,571,709
Members
48,796
Latest member
Greg L.
Top