Переменные экземпляра в сравнении с переменными класса в Python

У меня есть классы Python, из которых мне нужен только один экземпляр во время выполнения, поэтому достаточно будет иметь атрибуты только один раз для каждого класса, а не для экземпляра. Если будет более одного экземпляра (чего не будет), все экземпляры должны иметь одинаковую конфигурацию. Интересно, какой из следующих вариантов будет лучше или более "идиоматичным" Python.

Переменные класса:

class MyController(Controller):

  path = "something/"
  children = [AController, BController]

  def action(self, request):
    pass

Переменные экземпляра:

class MyController(Controller):

  def __init__(self):
    self.path = "something/"
    self.children = [AController, BController]

  def action(self, request):
    pass

Ответ 1

Если у вас есть только один экземпляр в любом случае, лучше всего сделать все переменные per-instance, просто потому, что они будут доступны (немного) быстрее (на один уровень меньше "поиска" из-за "наследования" от класса к пример), и нет недостатков, чтобы взвесить это небольшое преимущество.

Ответ 2

повторив эхо-запрос Майка и Алекса и добавив свой собственный цвет...

используя атрибуты экземпляра, типичный, более идиоматический Python. атрибуты класса не используются часто - по крайней мере, не в производственном коде за последние 13 лет подряд Python. то же самое верно для статических методов и методов класса... просто не очень распространено, если нет конкретного варианта использования или аберрантного программиста, желающего показать себя, они знают какой-то неясный угол программирования на Python.

alex упоминает в своем ответе, что доступ будет (немного) быстрее из-за одного меньшего уровня поиска... позвольте мне уточнить для тех, кто еще не знает, как это работает, это очень похоже на переменный доступ - поиск происходит в следующем порядке:

  • локальные
  • nonlocals
  • Глобал
  • Модульное

для доступа к атрибуту, порядок:

  • экземпляр
  • класса
  • базовые классы, определенные в MRO (порядок разрешения метода)

в приведенном выше примере, скажем, вы ищете атрибут path. когда он встречает ссылку типа "self.path", Python сначала рассмотрит атрибуты экземпляра для соответствия; когда это не удается, он проверяет класс, из которого был создан объект. наконец, он будет искать базовые классы. как сказал alex, если ваш атрибут найден в экземпляре, он не будет отнесен к классу, следовательно, ваш небольшой бит экономии времени.

однако, если вы настаиваете на атрибутах класса, вам придется отказаться от этого крошечного уровня производительности, или ваша другая альтернатива - ссылаться на объект через класс вместо экземпляра, например, MyController.path вместо self.path. что прямой поиск, который будет охватывать отложенный поиск, но, как указывает alex ниже, глобальная переменная, поэтому вы теряете тот бит, который, по вашему мнению, собираетесь сохранить (если вы не создадите локальную ссылку на имя класса [global]).

Ответ 3

Если вы сомневаетесь, вероятно, вам нужен атрибут экземпляра.

Атрибуты класса лучше всего зарезервировать для особых случаев, когда они имеют смысл. Единственным распространенным случаем использования являются методы. Необычно использовать атрибуты класса для констант только для чтения, которые должны знать экземпляры (хотя единственное преимущество в этом состоит в том, что вы также хотите получить доступ из-за пределов класса), но вы, безусловно, должны быть осторожны в отношении хранения любого состояния в них, что редко, чего вы хотите. Даже если у вас будет только один экземпляр, вы должны написать класс, как и любой другой, что обычно означает использование атрибутов экземпляра.