Атрибуты экземпляра хранятся в экземпляре, поэтому наследование здесь совершенно не имеет значения. Помните, что когда метод родительского класса вызывается для дочернего экземпляра, метод, который метод получает в качестве первого аргумента (self
), является дочерним экземпляром:
>>> class Foo:
... def __init__(self):
... print("In Foo.__init__, self is {}".format(self))
...
>>> class Bar(Foo): pass
...
>>> b = Bar()
In Foo.__init__, self is <__main__.Bar object at 0x7fd230244f60>
>>>
Лучше ли хранить их как локальная переменная в дочернем классе функций, а затем получить к ним доступ? (В случае, если он используется несколько раз)
Только для атрибутов, которые используются в ограниченном l oop (разрешение атрибута немного медленнее, чем разрешение локальной переменной) AND Профилирование показывает, что в этой точке есть узкое место. Но также не ожидайте значительного ускорения ...
На практике, если вам приходится беспокоиться о таких микрооптимизациях, скорее всего, реальное решение - либо переосмыслить ваш дизайн и реализацию, либо повторно реализовать критические разделы. кода в C.
Как и в коде, переменные не инициализируются в методе init . Это замедлит работу программы
Не совсем, за исключением накладных расходов на вызов obj.add()
. НО :
Это делается таким образом, потому что все атрибуты класса не являются необходимыми для всех операций. Поэтому, когда и как требуется, они инициализируются и используются.
Неправильный дизайн. Если вы хотите отложенную инициализацию для какого-либо атрибута, используйте property
или некоторый пользовательский дескриптор . Это гарантирует, что ваши объекты всегда будут иметь ожидаемые атрибуты, что бы ни случилось.
Если в родительском классе
* много переменных 10+ (включая массивы и объекты модели данных) 1038 * «Много» атрибутов в классе часто является запахом дизайна. Здесь нет строгого и быстрого правила - в некоторых случаях требуется немало атрибутов - но есть вероятность, что у вашего класса слишком много ответных возможностей, и его лучше было бы реорганизовать в набор наименьших классов, каждый из которых имеет одну четко определенную ответственность.
И нет, копирование и вставка инициализации атрибутов родительского класса в дочерний класс в любом случае не ускорит ваш код - это просто сделает обслуживание бесполезно сложнее и увеличит риски появления ошибок при смене родителя или детский класс. Я бы лично обозначил это как полный WTF, но я не известен своим врожденным чувством дипломатии; -)
EDIT :
На самом деле одна вещь, которую я здесь не упомянул, другая главная причина, по которой я создаю переменные вне init, заключается в том, что я использую шаблон фабричного дизайна в своем коде. И я динамически создаю классы, используя
def _create(pkg):
exec('import api.' + pkg + 'Helper as Creator');
return eval('Creator' + '.' + pkg + 'Helper()' )
Err ... Возможно, вам будет интересно узнать о некоторых функциях Python, таких как importlib.import_module
и getattr
. Как правило, всякий раз, когда вы рассматриваете возможность использования eval
или exec
, убедитесь, что есть лучшее (=> более безопасное, более явное и гораздо более удобное в обслуживании) решение. Я использую Python уже более 20 лет (для личных и профессиональных проектов), и мне все еще нужно найти случай, когда у меня была законная причина использовать eval
или exec
.
Кроме того, вы не опубликовали ту часть кода, которая фактически «динамически создает класс», но динамическое создание классов не налагает никаких ограничений или обходных путей (по сравнению с определениями «stati c») - вы все равно можете дать своему классу правильный инициализатор, свойства или любой другой пользовательский дескриптор et c. Если вы также используете exec̀̀
/ eval
для создания своего класса, то и здесь есть гораздо лучшие способы.
Мои 2 цента ...