__bases__ misleading error message

Ian Kelly ian.g.kelly at gmail.com
Sat Jan 24 17:16:45 EST 2015


On Sat, Jan 24, 2015 at 3:02 PM, Mario Figueiredo <marfig at gmail.com> wrote:
> In article <mailman.18102.1422136703.18130.python-list at python.org>,
> tjreedy at udel.edu says...
>>
>> >      "__main__"
>> >      from module import a_name
>>
>> A module is a namespace associating names with objects.  This statememt
>> says to import the a_name to object association from module and add it
>> to __main__
>>
>> >      y = a_name + 1
>>
>> This statement uses the imported association in __main__ to access the
>> object and add 1, and bind 'y' to the resulting object.
>
>
> But I'm being told the interpreter has no knowledge of a variable name.
> So, how does the interpreter know, once it reaches the assigment line
> above, how to map a_name to the correct object in memory?

No, you're being told that the *object* doesn't know the names of the
variables that it's bound to. In the context above, the variable is
right there under that name in the globals dict, as can be seen in the
disassembly:

>>> import dis
>>> dis.dis("y = a_name + 1")
  1           0 LOAD_NAME                0 (a_name)
              3 LOAD_CONST               0 (1)
              6 BINARY_ADD
              7 STORE_NAME               1 (y)
             10 LOAD_CONST               1 (None)
             13 RETURN_VALUE

Now what happens in the byte code if we try to access an attribute on
that object?

>>> dis.dis("a_name.__bases__")
  1           0 LOAD_NAME                0 (a_name)
              3 LOAD_ATTR                1 (__bases__)
              6 RETURN_VALUE

1) The value of a_name is looked up and pushed onto the stack.

2) The interpreter attempts to load the attribute __bases__ of
whatever object is on the top of the stack. There is no name
associated with that object at this point; it's just an object.

Now imagine if the Python code in question were instead this:

    def get_an_object(): return "foo"
    get_an_object().__bases__

Would you really expect the interpreter to come up with a message like
"Return value of get_an_object() has no attribute '__bases__'"?



More information about the Python-list mailing list