Question about math.pi is mutable

Chris Angelico rosuav at gmail.com
Sun Nov 8 10:11:26 EST 2015


On Mon, Nov 9, 2015 at 12:42 AM, BartC <bc at freeuk.com> wrote:
> Sorry, you'll have to assume I'm very stupid.
>
> What exactly is being looked up, and in what?
>
> From what I can understand in your example:
>
> * You are calling shutil.copyfileobj with two arguments, which happen to be
> instances of classes Source and Dest.
>
> * Let's say these are known as src and dst inside .copyfileobj.
>
> * .copyfileobj then calls methods src.read() dst.write().
>
> * Each of these method calls has the form A.B() which seems to me to be
> little different from shutil.copyfileobj().
>
> So to get back to what I was saying, does this lookup involving searching
> for method B in object A, and if so, does it actually do a search by name?
>
> (Someone mentioned a precalculated hash, of "A", or of "src" or "dst", use
> used, but still, it's looking something up in a table, and a hash table
> lookup I believe still requires an string compare to check if you've got the
> right entry.)

The lookups I'm talking about happen pretty much anywhere. Firstly,
this function:

def f():
    shutil.copyfileobj(src, dst)

looks up the global name 'shutil' (that's one dict lookup - module
globals are a dictionary), then performs an attribute lookup on the
resulting object with the name 'copyfileobj', then looks up the two
global names 'src' and 'dst'.

In fact[1], those strings can be found in f.__code__.co_names, and the
byte-code identifies them by their indices in that tuple. These are
str objects (note that this means they can be any legal Unicode
string; "шутил.цопыфилеобй(срц, дст)" is just as valid), and their
hashes will normally be precomputed to save time. Now, things are a
bit different with function-locals; the compiler always knows which
names they are, and it can compile things differently. Compare:

def f(src):
    shutil.copyfileobj(src, dst)

Instead of looking up a global name 'src', this now looks up a local
name. They're identified by slot positions, so the compiler simply
knows that "src" is in slot #0, and instead of looking anything up,
simply says "load the thing in slot #0". There can also be other
levels of indirection, such as __getattr__ and __getattribute__, which
affect how stuff gets looked up. But otherwise, name lookups generally
involve poking a dict with a string and taking what comes back
(possibly replacing KeyError with NameError or AttributeError as the
case may be).

ChrisA

[1] Assuming we're using CPython, or something which uses the same
byte-code; this is NOT a language requirement - none of this is.



More information about the Python-list mailing list