Path: csiph.com!x330-a1.tempe.blueboxinc.net!usenet.pasdenom.info!aioe.org!feeder.news-service.com!news2.euro.net!newsgate.cistron.nl!newsgate.news.xs4all.nl!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.000 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'sure.': 0.05; 'builtins': 0.07; 'compiler': 0.07; 'does.': 0.07; 'function,': 0.07; 'int,': 0.07; 'python': 0.08; 'bind': 0.09; 'deliberately': 0.09; 'dict': 0.09; 'len,': 0.09; 'likely.': 0.09; 'only,': 0.09; 'syntax': 0.11; 'wed,': 0.12; 'wrote:': 0.15; '(well,': 0.16; 'ah!': 0.16; 'from:addr:rosuav': 0.16; 'from:name:chris angelico': 0.16; 'len': 0.16; 'lookup': 0.16; 'quite.': 0.16; 'subject:Early': 0.16; 'variable.': 0.16; '\xa0for': 0.16; 'algorithm': 0.16; 'static': 0.16; 'pm,': 0.16; 'def': 0.16; 'aug': 0.19; 'int': 0.19; 'loading': 0.19; 'slightly': 0.19; 'variable': 0.21; "aren't": 0.22; 'maybe': 0.22; "doesn't": 0.22; 'header:In-Reply-To:1': 0.22; 'stuff': 0.22; 'trying': 0.23; 'assume': 0.23; 'dictionary': 0.23; 'interpreted': 0.23; 'thus': 0.23; 'code': 0.24; 'there.': 0.25; 'saying': 0.26; 'fine': 0.26; 'skip:b 20': 0.26; 'tried': 0.27; "i'm": 0.27; 'work.': 0.28; 'knowing': 0.28; 'tables': 0.28; 'bit': 0.28; 'message-id:@mail.gmail.com': 0.28; 'forgot': 0.29; 'variables': 0.29; 'problem': 0.29; 'arithmetic': 0.30; 'binding': 0.30; 'exist.': 0.30; 'hash': 0.30; 'values,': 0.30; 'yet': 0.30; 'compare': 0.31; 'this.': 0.31; 'chris': 0.32; "i'll": 0.33; 'actually': 0.33; "i've": 0.33; 'to:addr:python-list': 0.34; 'done.': 0.34; 'post': 0.34; "can't": 0.34; 'things': 0.34; 'all.': 0.35; 'function.': 0.35; 'integer': 0.35; "isn't": 0.35; 'probably': 0.35; 'question': 0.35; 'actual': 0.35; 'supposed': 0.35; 'idea': 0.36; 'assigned': 0.36; 'optimization': 0.36; 'convenient': 0.37; 'anything': 0.37; 'unless': 0.37; 'but': 0.37; 'could': 0.37; 'using': 0.37; 'received:google.com': 0.38; 'received:209.85': 0.38; 'subject:: ': 0.38; 'steven': 0.38; 'think': 0.38; 'case,': 0.38; "there's": 0.39; 'to:addr:python.org': 0.39; 'received:209': 0.40; 'body': 0.63; 'human': 0.63; '(4)': 0.64; 'kept': 0.67; 'profile': 0.71; 'million': 0.75; 'with,': 0.77; 'either,': 0.84; 'heh.': 0.84; 'locals': 0.84; 'scale),': 0.84; 'local,': 0.91 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :content-type:content-transfer-encoding; bh=uZTHJ8uCtsHs4dTIFsv+w1FKq+PgLpTGRLVDi+bMi/8=; b=Njnk84KsIY2aAqNWxoDCWW7Bb9ivwL8kFnXfl789HqVrMcqUGlkQZS+wGQPIOIYwPl +xjA3KIsxC+ettD81TP5fH4MDqPAem9BmGqq0EtKgvYIUC8/QsHKKem4n46JGL10ljBU ys9MMX6notNXAKOpzXr/lhjIsyUKpPiXB4JRQ= MIME-Version: 1.0 In-Reply-To: <4e39a6b5$0$29973$c3e8da3$5496439d@news.astraweb.com> References: <4e39200f$0$30001$c3e8da3$5496439d@news.astraweb.com> <4e39a6b5$0$29973$c3e8da3$5496439d@news.astraweb.com> Date: Wed, 3 Aug 2011 23:24:09 +0100 Subject: Re: Early binding as an option From: Chris Angelico To: python-list@python.org Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 77 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1312410252 news.xs4all.nl 23892 [2001:888:2000:d::a6]:40734 X-Complaints-To: abuse@xs4all.nl Xref: x330-a1.tempe.blueboxinc.net comp.lang.python:10830 On Wed, Aug 3, 2011 at 8:51 PM, Steven D'Aprano 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): >> =A0 =A0len =3D len =A0# localize len >> =A0 =A0for i in x: >> =A0 =A0 =A0 =A0len(i) =A0# use it exactly as you otherwise would > > That can't work. The problem is that because len is assigned to in the bo= dy > of the function, the Python compiler treats it as a local variable. So th= e > line len=3Dlen is interpreted as len =3D len, which doesn't= yet > exist. There's no way of saying len =3D len in the body of= the > function. Duh. Forgot that. Without convenient syntax like "len =3D ::len" to do this, it's not advisable. > (4) manual lookup: len =3D builtins.__dict__['len'] =A0# untested > > I don't recommend that last one, unless you're deliberately trying to wri= te > 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