Ответ 1
Как заметил Wooble в комментарии, блок класса создает новую область. Проблема в том, что имена в области блока классов недоступны для областей, вложенных в эту область. Это упоминается в документации:
Объем имен, определенных в блоке класса, ограничен блоком класса; он не распространяется на кодовые блоки методов - это включает в себя выражения и выражения генератора, поскольку они реализованы с использованием области действия.
Я не могу найти источник этого права сейчас, но где-то (я думаю, по вопросу StackOverflow) я нашел одно правдоподобное обоснование для этого: если класс def был доступен во вложенных блоках, имена методов будут затенять глобальные функции, в том числе встроенных. Это создало бы неудобство для создания классов с методами с короткими простыми именами, но также с использованием встроенных функций с тем же именем. Например, вы не могли этого сделать:
class SomeDataStructure(object):
def sum(self):
return sum(self._data)
def otherCalc(self):
return sum(item for item in somethingElse)
Если блок класса находился в области видимости внутри методов, это вызовет бесконечную рекурсию, так как внутренний вызов sum
имел бы доступ к имени метода и вызывал бы этот метод вместо встроенной функции sum
. Аналогичным образом, другие методы, такие как метод otherCalc
, больше не будут иметь доступа к глобальной функции сумм для собственного использования, но всегда будут получать метод. Ответ на другой вопрос SO описывает это, говоря "это потому, что вы должны использовать self
для доступа к методам в Python".
Теперь этот аргумент действительно имеет смысл только для функций внутри классов, потому что тела функций не выполняются, когда def
есть, но тела класса выполняются, когда оператор class
. Однако я думаю, что если вы объедините то, что я сказал выше, с понятиями в этом сообщении в блоге, вы получите разумное обоснование. А именно, вложенные классы не были - и до сих пор не считаются стилем, который стоит поддержать. Однако функции внутри классов, конечно, обычны. Простейший способ обработки использования функции внутри внутри класса заключался в том, чтобы блок class
не передавал свои имена ни в какие вложенные области. Было бы лучше, если бы он передавал свои имена вложенным классам, но не вложенные функции, но это было бы более сложным правилом, и никто не заботился бы о поддержке вложенных классов, чтобы сделать это стоящим.