[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

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

aspineux

1/14/2008 6:40:00 PM


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.

13 Answers

Chris Mellon

1/14/2008 6:50:00 PM

0

On Jan 14, 2008 12:39 PM, aspineux <aspineux@gmail.com> wrote:
>
> 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.

Neil Cerutti

1/14/2008 6:54:00 PM

0

On Jan 14, 2008 1:39 PM, aspineux <aspineux@gmail.com> wrote:
>
> 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.

>>> def f():
.... 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.

--
Neil Cerutti <mr.cerutti+python@gmail.com>

aspineux

1/14/2008 7:07:00 PM

0

On Jan 14, 7:49 pm, "Chris Mellon" <arka...@gmail.com> wrote:
> On Jan 14, 2008 12:39 PM, aspineux <aspin...@gmail.com> wrote:
>
>
>
> > 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.

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 ?


Paul Rubin

1/14/2008 8:09:00 PM

0

aspineux <aspineux@gmail.com> writes:
> 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()

Steven D'Aprano

1/14/2008 9:38:00 PM

0

On Mon, 14 Jan 2008 12:08:52 -0800, Paul Rubin wrote:

> aspineux <aspineux@gmail.com> writes:
>> 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.


--
Steven

Tim Chase

1/14/2008 10:07:00 PM

0

> 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



Paul Rubin

1/14/2008 11:15:00 PM

0

Steven D'Aprano <steve@REMOVE-THIS-cybersource.com.au> writes:
> 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() .

Steven D'Aprano

1/15/2008 3:14:00 AM

0

On Mon, 14 Jan 2008 15:15:28 -0800, Paul Rubin wrote:

> Steven D'Aprano <steve@REMOVE-THIS-cybersource.com.au> writes:
>> 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() .


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

Sorry if I misunderstood you in the first place.




--
Steven

aspineux

1/15/2008 2:03:00 PM

0

On Jan 15, 12:15 am, Paul Rubin <http://phr...@NOSPAM.invalid> wrote:
> Steven D'Aprano <st...@REMOVE-THIS-cybersource.com.au> writes:
> > 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() .

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)]

aspineux

1/15/2008 2:18:00 PM

0

On Jan 14, 8:07 pm, aspineux <aspin...@gmail.com> wrote:
> On Jan 14, 7:49 pm, "Chris Mellon" <arka...@gmail.com> wrote:
>
> > On Jan 14, 2008 12:39 PM, aspineux <aspin...@gmail.com> wrote:
>
> > > 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.
>
> 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.