У меня есть классы 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
Ответы:
Если в любом случае у вас есть только один экземпляр, лучше всего сделать все переменные для каждого экземпляра просто потому, что доступ к ним будет осуществляться (немного) быстрее (на один уровень «поиска» меньше из-за «наследования» от класса к экземпляру), и у этого небольшого преимущества нет недостатков.
источник
python -mtimeit
но только что сделав это в python3.4, я отмечаю, что доступ кint
переменной класса на самом деле примерно на 5-11 наносекунд быстрее, чем то же, что и переменная экземпляра на моей старой рабочей станции - не уверен, что codepath делает это так.Повторяя совет Майка и Алекса и добавляя свой собственный цвет ...
Использование атрибутов экземпляра является типичным ... более идиоматическим Python. Атрибуты класса используются не так часто, поскольку их варианты использования специфичны. То же самое верно для статических методов и методов класса по сравнению с "обычными" методами. Это специальные конструкции, предназначенные для конкретных случаев использования, иначе это код, созданный ошибочным программистом, желающим показать, что он знает какой-то неясный угол программирования на Python.
Алекс упоминает в своем ответе, что доступ будет (немного) быстрее из-за на один уровень поиска меньше ... позвольте мне еще пояснить для тех, кто еще не знает, как это работает. Это очень похоже на доступ к переменным - порядок поиска:
Для доступа к атрибутам порядок следующий:
Оба метода работают «наизнанку», то есть сначала проверяются наиболее локальные объекты, а затем последовательно проверяются внешние слои.
В приведенном выше примере предположим, что вы ищете
path
атрибут. Когда он встречает ссылку вроде "self.path
", Python сначала проверяет атрибуты экземпляра на соответствие. Когда это не удается, он проверяет класс, из которого был создан объект. Наконец, он будет искать базовые классы. Как заявил Алекс, если ваш атрибут найден в экземпляре, его не нужно искать в другом месте, что позволяет сэкономить немного времени.Однако, если вы настаиваете на атрибутах класса, вам понадобится дополнительный поиск. Или ваша другая альтернатива - ссылаться на объект через класс вместо экземпляра, например,
MyController.path
вместоself.path
. Это прямой поиск, который позволяет обойти отложенный поиск, но, как упоминает ниже Алекс, это глобальная переменная, поэтому вы теряете тот бит, который, как вы думали, собирались сохранить (если вы не создадите локальную ссылку на [глобальное] имя класса ).Суть в том, что вы должны использовать атрибуты экземпляра большую часть времени. Тем не менее, будут случаи, когда атрибут класса является правильным инструментом для работы. Код, использующий и то, и другое одновременно, потребует наибольшего усердия, потому что при использовании
self
вы получите только объект атрибута экземпляра и затеняет доступ к атрибуту класса с тем же именем. В этом случае вы должны использовать атрибут доступа по имени класса, чтобы ссылаться на него.источник
MyController
в глобальных объектах, поэтому общая стоимость выше, чемself.path
гдеpath
находится переменная экземпляра (посколькуself
является локальной для метода == сверхбыстрый поиск).В случае сомнений вам, вероятно, понадобится атрибут экземпляра.
Атрибуты класса лучше всего зарезервировать для особых случаев, когда они имеют смысл. Единственный очень распространенный вариант использования - это методы. Это не редкость , чтобы использовать класс атрибуты только для чтения констант , что экземпляры должны знать (хотя единственное преимущество этого, если вы хотите получить доступ из вне класса), но вы , конечно , должны быть осторожными о хранении любого состояния в них , что бывает редко. Даже если у вас будет только один экземпляр, вы должны написать класс так же, как и любой другой, что обычно означает использование атрибутов экземпляра.
источник
avoid global variables
и их определение состоит в том, что глобальные переменные также являются переменными, объявленными как атрибуты класса. Тем не менее, собственное руководство по стилю Python ( PEP-8 ) должно быть первым местом, где можно найти вопросы такого рода. Тогда ваш собственный разум должен быть предпочтительным инструментом (конечно, вы также можете почерпнуть идеи, например, от Google).Тот же вопрос в производительности доступа к переменным класса в Python - код здесь адаптирован из @Edward Loper
К локальным переменным проще всего получить доступ, они в значительной степени связаны с переменными модуля, за которыми следуют переменные класса, за которыми следуют переменные экземпляра.
Есть 4 области, из которых вы можете получить доступ к переменным:
Тест:
Результат:
источник