Builtin dict should be callable, since a dict defines a funct ion
Bengt Richter
bokr at oz.net
Sat Dec 21 10:46:53 EST 2002
On Fri, 20 Dec 2002 12:59:48 -0600, sismex01 at hebmex.com wrote:
>> From: bokr at oz.net [mailto:bokr at oz.net]
>> Sent: Thursday, December 19, 2002 9:00 PM
>>
>> On Thu, 19 Dec 2002 18:17:03 -0800, Erik Max Francis
>> <max at alcyone.com> wrote:
>>
>> >Bengt Richter wrote:
>> >
>> > But why would this be helpful? A dictionary implements a mappable
>> > interface; a function implements are callable interface. They're
>> > different interfaces; why would dovetailing them into the
>> > same interface be beneficial?
>>
>> You can pass a reference to a dict to something that expects
>> a function, e.g., a sort. You could pass it as a memoized-result
>> proxy function in some context and catch KeyError to take care of
>> LRU caching update, etc.
>>
>> I'm sure many uses would turn up once the obstacle was removed, and
>> people thought of functions as mappings and vice versa ;-)
>>
>
>You can already do this.
>
>Let's say you need a function which works like a (callable)
>dictionary for retrieving values. Instead of creating a new
>function or subclassing dict, pass it a reference to:
>
> d.__getitem__
>
>and voila, there's your reference to a function-behaving-like-
>a-dictionary.
>
True, but it is not quite the same thing. On the surface I was not
asking for more, so your answer (and the same pointed out by others)
is right on as far as it goes (I was a bit chagrined not to have thought
of this obvious thing in the first place). But I still have a nagging
dissatisfaction with the answer.
If I know that a dict will have a _default_ function-style interface
as if its class were defined with __call__ = __getitem__, then I can
make an anonymous collection of function and dict objects, e.g., a list
fdmix = [f1,f2,d1,d2]
and depend on the callable assumption for all elements.
Now what power does this give me over the following list?
fdmix2 = [f1,f2,d1.__getitem__, d2.__getitem__]
Well, this list does not carry the same information. I have been
forced to throw away the possibility of distinguishing and acting
differently based on type _if_ that is useful for another use of
the list (e.g., passing the collection to different places).
I admit that a subclass will do what I want, but there is a performance
hit for some reason (see below).
Note that speed could make a lot of difference if you were passing a function
that processed pixels for example:
>>> import timefuns
>>> def noop(k): pass
...
>>> d={'xx':123}
>>> class D(dict): __call__ = dict.__getitem__
...
>>> dc = D(d)
>>> df = d.__getitem__
>>> dc.__name__ = 'D inst'
>>> calls = [(noop,'xx'),(dc,'xx'),(df,'xx')]
>>> timefuns.timefuns(100000, calls)
timing oh: 0.000015 ratio
noop: 0.000009 1.00
D inst: 0.000012 1.29
__getitem__: 0.000004 0.48
Timing overhead is time measured by t1-t0 in
t0=time.clock()
t1=time.clock()
where otherwise there is a call to the function as a single line
in between, in thefunction timing loop.
This overhead is subtracted out to get a better relative time between
the functions. The ratios are wrt to the first function in the list.
Note that that d.__getitem__ is almost twice as fast as even just
calling a noop function with the same single parameter.
So I think there is more than one argument in favor of this simple
backwards-compatible change ;-)
Regards,
Bengt Richter
More information about the Python-list
mailing list