Объем имен, определенных в блоке классов, не распространяется на блоки методов. Почему это?

Читая документацию, я натолкнулся на следующий параграф:

Область определяет видимость имени внутри блока. Если локальная переменная определена в блоке, ее область включает этот блок. Если определение происходит в функциональном блоке, область действия распространяется на любые блоки, содержащиеся в определяющем, если только содержащийся блок не вводит другую привязку для имени. Объем имен, определенных в блоке класса, ограничен блоком класса; он не распространяется на кодовые блоки методов – это включает в себя выражения и выражения генератора, поскольку они реализованы с использованием области функций.

  • Мне нужно узнать об объектах, или я могу сэкономить время и просто изучить словари?
  • Python эквивалент Ruby's 'method_missing'
  • Почему Python, похоже, рассматривает переменные экземпляра как общие между объектами?
  • Создание сценария Python Объектно-ориентированный
  • Должны ли внутренние методы класса возвращать значения или просто изменять переменные экземпляра в python?
  • Что такое mixin и почему они полезны?
  • Я решил попробовать получить доступ к переменной класса из метода самостоятельно:

    >>> class A(): i = 1 def f(self): print(i) >>> a = A() >>> ai 1 >>> af() Traceback (most recent call last): File "<pyshell#7>", line 1, in <module> af() File "<pyshell#4>", line 4, in f print(i) NameError: global name 'i' is not defined 

    Я знаю, что к переменной i можно получить доступ, явно указывая на имя класса Ai :

     >>> a = A() >>> class A(): i = 1 def f(self): print(Ai) >>> a = A() >>> af() 1 

    Вопрос в том, почему разработчики языка сделали переменные класса невидимыми из методов? В чем причина этого?

  • Приложение Python ничего не печатает при запуске отсоединенного в докере
  • Создание метода, который одновременно является методом экземпляра и класса
  • используйте xml.etree.elementtree для записи хорошо отформатированных xml-файлов
  • wxPython: вызов события вручную
  • как передать переменную из включенного шаблона в шаблон, где он включен?
  • Как отменить каждое слово в строке, но в том же предложении?
  • 2 Solutions collect form web for “Объем имен, определенных в блоке классов, не распространяется на блоки методов. Почему это?”

    Это, по-видимому, связано с использованием явного параметра self и требованием, чтобы все вызовы методов и атрибуты экземпляра явно использовали self . Было бы, по крайней мере, странно, если бы необычный случай доступа к функции класса класса как нормальной функции был бы намного проще, чем обычный случай обращения к нему как с помощью метода self . Обычно переменные класса также доступны через экземпляр в Python.

    Напротив, в C ++ область видимости видима во всех методах, но вызов метода неявно передает this . Это, похоже, другой разумный выбор.

    Блок класса – это синтаксический сахар для создания словаря, который затем передается метаклассу (обычно type ) для создания объекта класса.

     class A: i = 1 def f(self): print(i) 

    Это примерно эквивалентно:

     def f(self): print(i) attributes = {'f': f, 'i': 1) A = type('A', (object,) attributes) 

    Таким образом, внешний вид i не имеет внешнего вида. Однако, очевидно, существует временная область для выполнения операторов в блоке классов. Было бы возможно, чтобы этот класс block desugar был чем-то более похож:

     def attributes(): i = 1 def f(self): print(i) return locals() A = type('A', (object,), attributes()) 

    В этом случае внешняя ссылка на i будет работать. Однако это будет «против зерна» философии объектной системы Python.

    У Python есть объекты, которые содержат атрибуты. На самом деле нет понятия «переменные», кроме локальных переменных в функциях (которые могут быть вложены для создания цепочки областей видимости). Голое имя просматривается как локальная переменная, затем во внешних областях (которые исходят от функций). Атрибуты просматриваются, используя синтаксис точечного имени, на других объектах, и вы всегда указываете, какой объект искать.

    Существует протокол для разрешения ссылок на атрибуты, в котором говорится, что когда attribute не найден в obj , obj.attribute может быть разрешен путем поиска в классе obj (и его базовых классов, используя порядок разрешения метода). На самом деле, как методы найдены; когда в вашем примере вы выполнили af() , объект не содержит атрибута f , поэтому выполняется поиск класса a (который есть A ) и определение метода найдено.

    Наличие атрибутов класса, автоматически доступных во внешней области для всех методов, было бы странным, потому что никакой другой атрибут не работает таким образом. Это также имеет следующие недостатки:

    1. Функции, определенные вне класса и назначенные ему позже, должны будут использовать другой синтаксис для обозначения атрибута класса, чем функции, определенные как часть класса.
    2. Поскольку он короче, он будет поощрять ссылку на атрибуты класса, включая staticmethods и classmethods, как голые имена: thing а не использование Class.thing или self.thing . Это делает их похожими на глобалы модулей, когда они не являются (определения методов обычно достаточно коротки, чтобы вы могли легко видеть, что они не определены локально).
    3. Обратите внимание: поиск атрибутов self позволяет им играть лучше с подклассами, так как позволяет подклассам переопределять атрибут. Вероятно, это не так уж важно для «констант класса», но это очень важно для staticmethods и classmethods.

    Это основные причины, которые я вижу, но в конечном итоге это просто выбор, который создали дизайнеры Python. Вы считаете странным, что у вас нет этой неявной способности ссылаться на переменные класса, но я считаю неявный доступ к переменной класса и экземпляра на таких языках, как C ++ и Java, странными. У разных людей разные мнения.

    Python - лучший язык программирования в мире.