Вложенные функции Python

У меня такой код:

def write_postcodes(self):
    """Write postcodes database. Write data to file pointer. Data 
    is ordered. Initially index pages are written, grouping postcodes by
    the first three characters, allowing for faster searching."""
    status("POSTCODE", "Preparing to sort...", 0, 1)
    # This function returns the key of x whilst updating the displayed 
    # status of the sort.
    ctr = 0
    def keyfunc(x):
        ctr += 1
        status("POSTCODE", "Sorting postcodes", ctr, len(self.postcodes))
        return x
    sort_res = self.postcodes[:]
    sort_res.sort(key=keyfunc)

Но ctr отвечает с NameError:

Traceback (most recent call last):
  File "PostcodeWriter.py", line 53, in <module>
    w.write_postcodes()
  File "PostcodeWriter.py", line 47, in write_postcodes
    sort_res.sort(key=keyfunc)
  File "PostcodeWriter.py", line 43, in keyfunc
    ctr += 1
UnboundLocalError: local variable 'ctr' referenced before assignment

Как я могу это исправить? Я думал, что невесты позволят мне это сделать. Я пробовал использовать "глобальный", но он все еще не работает.

Ответ 1

Так как вложенная функция не может перепроверять нелокальное имя (в Python 2, в Python 3, вы должны использовать оператор nonlocal, чтобы включить это), вам нужно выполнить инкремент без перезаписи barename (путем сохранения counter как элемент или атрибут некоторого имени, не как само имя). Например:

...
ctr = [0]
def keyfunc(x):
    ctr[0] += 1
    status("POSTCODE", "Sorting postcodes", ctr, len(self.postcodes))
    return x
...

и, конечно, используйте ctr[0] везде, где вы используете голый ctr сейчас в другом месте.

Ответ 2

От http://www.devshed.com/c/a/Python/Nested-Functions-in-Python/1/

Код в корпусе вложенной функции может доступ (но не переустановка) локальный переменные внешней функции, также известные как свободные переменные вложенных функция.

Итак, вам нужно явно передать ctr в keyfunc.

Ответ 3

Как объявить ctr вне класса, которому принадлежит write_postcodes, или любой другой класс/функция? Это сделает переменную доступной и доступной для записи.