Early binding as an option

Chris Angelico rosuav at gmail.com
Wed Aug 3 18:24:09 EDT 2011


On Wed, Aug 3, 2011 at 8:51 PM, Steven D'Aprano
<steve+comp.lang.python at pearwood.info> wrote:
> Chris Angelico wrote:
>
>> Ah! I was not aware of this, and thought that locals were a dictionary
>> too. Of course, it makes a lot of sense. In that case, the classic
>> "grab it as a local" isn't just loading down the locals dictionary
>> with more names and thus slower lookups.
>
> Er, not quite. Hash tables don't get slower as you add more items in them.

Whoops, sloppy English there. The locals dictionary isn't slower
because it gets more stuffed in it (well, maybe a dict will slow down
if you stuff a few million things in it vs having five, but not with
this scale), but that it's slower than alternatives.

>> No, I'm not sure. Unfortunately I have no convenient way to compare;
>
> Have you tried using the profiler?

I can profile the code the way it is. I can't profile the code the way
it isn't, with static lookups. I could compare global vs local, but
not global/local vs no lookup at all.

>> and secondly, that Pike is
>> able to optimize integer arithmetic by knowing that the value in
>> question is an int, and it will never be anything else.
>
> Much more likely.

Pike separates variables from their values, just as Python does. I've
actually stuffed strings into variables that are supposed to be int
only, and things work fine (a bit confusing for the human though!).
But you're right that it's probably simplifying other lookups, not the
actual variable name. I think the same consideration applies; if you
know exactly what you're working with, if you assume that x.__add__ is
not going to change, then you can optimize.

> Or you cheated and used a slightly different algorithm in Pike :)

Heh. No, I kept the algorithm exactly the same. I'll post the code if
you like :)

>> def func(x):
>>    len = len  # localize len
>>    for i in x:
>>        len(i)  # use it exactly as you otherwise would
>
> That can't work. The problem is that because len is assigned to in the body
> of the function, the Python compiler treats it as a local variable. So the
> line len=len is interpreted as <local>len = <local>len, which doesn't yet
> exist. There's no way of saying <local>len = <global>len in the body of the
> function.

Duh. Forgot that. Without convenient syntax like "len = ::len" to do
this, it's not advisable.

> (4) manual lookup: len = builtins.__dict__['len']  # untested
>
> I don't recommend that last one, unless you're deliberately trying to write
> obfuscated code :)

For that reason! Although using builtins in this way isn't a good idea
- there's no reason to do early binding late if you just bind to the
same thing that early binding early would have done. And
globals()["len"] doesn't work either, because builtins aren't
globals... blargh, there's really no simple way to do this. It's a
good thing I don't *need* to do anything like this, because it's not
the syntactically simple optimization that I thought it would be!

ChrisA



More information about the Python-list mailing list