Is this a bug?

Joshua Landau joshua at landau.ws
Mon Jul 15 12:13:12 EDT 2013


On 15 July 2013 16:50, Jack Bates <tdhfwh at nottheoilrig.com> wrote:
> Hello,
>
> Is the following code supposed to be an UnboundLocalError?
> Currently it assigns the value 'bar' to the attribute baz.foo
>
>    foo = 'bar'
>    class baz:
>       foo = foo

I have two responses because I'm not sure what you're saying. Take your pick.

----------------------------------

If you're getting an error from that, then yes. The code works fine for me.

I assume you're just jumping to conclusions and not testing code and
were doing something like:

foo = "Outside foo"
def this_will_break():
    foo
    foo = "Inside foo"

and wondering why it breaks. Is this correct?

If so, it's because Python has consistent ideas about whether
something is local to its scope -- some other languages will think
that foo is nonlocal *until* they see the assignment. Python knows
that foo will be assigned later in the function, so is a local
variable the whole time. Being local, the outside version refers to *a
different name*.

If you want them to refer to the same name, use "nonlocal" or
"global", depending on circumstance.

foo = "Outside foo"
def this_will_break():
    global foo
    foo
    foo = "Still outside foo (outside foo is changed too)"

----------------------------------------

ALTERNATIVELY

Are you saying you think that instead of doing what it does it should
raise an UnboundLocalError?

If so, then no. Assignments inside class bodies are special-cased in
Python. This is because all assignments refer to properties of "self"
on the LHS but external things too on the RHS. This is why you can do
"def x(): ..." instead of "def self.x(): ..." or some other weird
thing. There's also some extra special stuff that goes on.

In order to make this an UnboundLocalError, lots of dramatic and
unhelpful changes would have to take place, hence the current
behaviour. The current behaviour is useful, too.



More information about the Python-list mailing list