Values and objects

Steven D'Aprano steve+comp.lang.python at pearwood.info
Sun May 11 03:24:06 EDT 2014


On Sat, 10 May 2014 18:28:43 -0700, Ethan Furman wrote:

> On 05/10/2014 04:18 PM, Chris Angelico wrote:
>> On Sun, May 11, 2014 at 5:10 AM, Ethan Furman <ethan at stoneleaf.us>
>> wrote:
>>> And if you don't like that argument (although it is a perfectly sound
>>> and correct argument), think of the module name space:
>>>
>>>
>>> ret = spam
>>> spam = 23
>>>
>>> will net you a simple NameError, because spam has not yet been
>>> created.
>>
>> What about this, though:
>>
>> ret = int
>> int = 23
>>
>> That will *not* net you a NameError, because 'int' exists in an outer
>> scope (builtins). You can create a new module-scope variable and it
>> will immediately begin to shadow a builtin; you can delete that
>> variable and it will immediately cease to shadow that builtin. That's
>> the difference I'm talking about. With function-local variables, they
>> all have to exist (as other responses confirmed, that *is* a language
>> guarantee), even though some of them aren't bound to anything yet.
> 
> Well, with function variables they have to exist *when you use them*. ;)
> 
> This seems like more of a scoping issue than a "can we create variables
> in Python" issue.

Correct. The first line "ret = int" does a name lookup for "int", finds 
it in the built-ins, and binds it to "ret". The second line "int = 23" 
binds the object 23 to the name "int" in the current namespace, i.e. the 
globals. It has nothing to do with how variables are created.

By default, you can't do that inside a function because function scoping 
is special, not because function locals are kept inside slots. (1) They 
aren't always, not even in CPython, and (2) even if they are, an 
implementation could hide that fact and provide the same behaviour.

I say "by default" because with byte-code hacking you can. Suppose I 
write the function:

def special():
    spam = spam
    process(spam)

Under normal circumstances, this will fail, because the assignment 
"spam = ..." tells the compiler that spam is a local, and so the lookup 
for "... = spam" does a LOAD_FAST which fails. But if I hack the byte 
code, I can turn that LOAD_FAST into a LOAD_GLOBAL, which then gives 
behaviour just like Lua:

    spam (the local variable) = spam (the global variable)


Of course, this isn't a feature of Python the language. But with 
sufficient byte-code hacking skills, it is possible.


> I am curious, though, what other python's do with respect to function
> variables.

As far as I know, Jython and IronPython store them in a dict namespace, 
just like globals. See my previous responses to Chris.



-- 
Steven D'Aprano
http://import-that.dreamwidth.org/



More information about the Python-list mailing list