Values and objects

Steven D'Aprano steve+comp.lang.python at pearwood.info
Sat May 10 23:17:22 EDT 2014


On Sat, 10 May 2014 14:03:11 -0700, Devin Jeanpierre wrote:

> On Sat, May 10, 2014 at 12:10 PM, Ethan Furman <ethan at stoneleaf.us>
> wrote:
>> On 05/10/2014 02:32 AM, Chris Angelico wrote:
>>>
>>>
>>> Tell me, what may this function do in a compliant Python?
>>>
>>> def demo():
>>>      ret = spam
>>>      spam = 23
>>>      return ret
>>>
>>> In CPython, that'll raise UnboundLocalError, because the local
>>> variable 'spam' does already exist, and currently has no value (no
>>> object bound to it).
>>
>>
>> No, it does not exist -- or, more accurately, it does not exist *yet*
>> but will.  The fact that there is a slot waiting for what will be spam
>> is a cpython implementation detail.
> 
> The name of the exception is "UnboundLocalError". And the message says
> that we referred to a "local variable".
> 
> Also see the language reference:
> 
> "When a name is not found at all, a NameError exception is raised. If
> the name refers to a local variable that has not been bound, a
> UnboundLocalError exception is raised. UnboundLocalError is a subclass
> of NameError."
> 
> spam is referring to a local variable that has not been bound. This is
> not an implementation detail.

Of course not. What is an implementation detail is that there is a slot 
waiting to be filled for it, just like Ethan said. It's the existence of 
pre-allocated slots for locals which is an implementation detail, not 
whether a name is treated as local or not.


>> 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.
> 
> Because module level variables work differently from local variables.

But that is an implementation detail. IronPython and Jython use an 
ordinary dict for local variable namespaces, just like globals. Consider 
this example from Jython:

>>> spam = 9999
>>> def modify(namespace):
...     namespace['spam'] = 42
...
>>> def demo():
...     modify(locals())
...     spam = spam
...     return spam
...
>>> demo()
42



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



More information about the Python-list mailing list