This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: super() and del in the same method leads to UnboundLocalError
Type: Stage:
Components: Versions: Python 3.2, Python 3.4, Python 2.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: Miaou, mark.dickinson
Priority: normal Keywords:

Created on 2014-10-07 09:48 by Miaou, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (4)
msg228757 - (view) Author: Pierre-Antoine BRAMERET (Miaou) Date: 2014-10-07 09:48
Hi,

With the following code:

class Base(object): pass

class Foo(Base):
  def __init__(self):
    super(Foo,self).__init__()
    if False:
      del Foo


I expect that Foo() would give me a Foo instance. Instead, it raises the following exception:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __init__
    super(Foo,self).__init__()
UnboundLocalError: local variable 'Foo' referenced before assignment



I first suspected the "del Foo" statement is executed before the function is executed (while parsing or something), because the error tells Foo does not exists.

Howver, the problem is deeper than that: with the following modified code:

class Foo(Base):
  def __init__(self):
    assert 'Foo' in globals()
    assert Foo
    super(Foo,self).__init__()
    if False:
      del Foo

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in __init__
    super(Foo,self).__init__()
UnboundLocalError: local variable 'Foo' referenced before assignment



So: Foo IS in globals(), but cannot be accessed through Foo in the class because of the presence of 'del Foo' in the never reached part of the method.
msg228759 - (view) Author: Pierre-Antoine BRAMERET (Miaou) Date: 2014-10-07 09:52
Sorry, I miscopied the last Traceback. Please find the following:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in __init__
    assert Foo
UnboundLocalError: local variable 'Foo' referenced before assignment
msg228764 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2014-10-07 10:38
So while the behaviour is surprising, the language is behaving as designed:  the target of `del` is considered to be a local variable for the entire function definition.  (In much the same way, the targets of simple assignments are considered local, so if you'd assigned to "Foo" in the "if False:" block, you'd see the same error.)

The behaviour is documented here: https://docs.python.org/3.4/reference/executionmodel.html#naming-and-binding

Note particularly these bits:

"If a name is bound in a block, it is a local variable of that block, [...]"

"A target occurring in a del statement is also considered bound for this purpose [...]"

See also this FAQ: https://docs.python.org/3/faq/programming.html#id8

I wonder whether it's worth updating the FAQ to mention that `del` is considered to bind names in this way.
msg228766 - (view) Author: Pierre-Antoine BRAMERET (Miaou) Date: 2014-10-07 12:31
Hi,

Tanks for your clear answer. I find it surprising that "del" bounds the name locally, but with little more thinking, it is not...
History
Date User Action Args
2022-04-11 14:58:08adminsetgithub: 66764
2014-10-07 12:31:06Miaousetstatus: open -> closed
resolution: not a bug
messages: + msg228766
2014-10-07 10:38:59mark.dickinsonsetnosy: + mark.dickinson
messages: + msg228764
2014-10-07 09:52:18Miaousetmessages: + msg228759
2014-10-07 09:48:15Miaoucreate