python: займет ли класс с большим количеством методов больше времени для инициализации?
У меня есть программа, которая должна непрерывно создавать тысячи объектов из класса, который имеет около 12–14 методов. Приведет ли тот факт, что они имеют сложный класс, к быстродействию из-за создания более простого объекта, такого как список или словарь, или даже другого объекта с меньшим количеством методов?
Некоторые подробности о моей ситуации: у меня есть куча "текстовых" объектов, которые постоянно создают и обновляют "распечатки" их содержимого. У объектов печати есть много методов, но только несколько атрибутов. Объекты печати не могут содержаться в текстовых объектах, потому что текстовые объекты должны быть "многократно используемыми" и делать несколько независимых копий своих отпечатков, чтобы исключить просто замену атрибутов объектов печати при обновлении.
Мне лучше,
- Постоянно создавать новые объекты печати со всеми их методами при обновлении приложения?
- Распутывание класса и превращение объектов печати в простые структуры и методы в независимые функции, которые принимают объекты в качестве аргументов?
Я предполагаю, что это будет зависеть от того, есть ли большие затраты, связанные с созданием новых объектов со всеми включенными в них методами, вместо того, чтобы импортировать все независимые функции туда, где они были бы вызваны как методы объекта.
3 ответа
Неважно, насколько сложный класс; когда вы создаете экземпляр, вы сохраняете только ссылку на класс вместе с экземпляром. Все методы доступны через одну ссылку.
Нет, это не должно иметь значение.
Учтите, что когда вы делаете следующее:
a = Foo()
a.bar()
Призыв к bar
Этот метод фактически переводится под обложками:
Foo.bar(a)
Т.е. bar
является "статическим" в определении класса, и существует только один экземпляр функции. Когда вы смотрите на это так, это говорит о том, что нет, не будет существенного влияния числа методов. Методы создаются при первом запуске программы Python, а не при создании объектов.
Я сделал некоторое тестирование.
У меня есть следующая функция:
def call_1000000_times(f):
start = time.time()
for i in xrange(1000000):
f(a=i, b=10000-i)
return time.time() - start
Как вы можете видеть, эта функция берет другую функцию, вызывает ее 1000000 раз и возвращает время ожидания в секундах.
Я также создал два класса:
Небольшой класс:
class X(object):
def __init__(self, a, b):
self.a = a
self.b = b
И довольно большой:
class Y(object):
def __init__(self, a, b):
self.a = a
self.b = b
def foo(self): pass
def bar(self): pass
def baz(self): pass
def anothermethod(self):
pass
@classmethod
def hey_a_class_method(cls, argument):
pass
def thisclassdoeswaytoomuch(self): pass
def thisclassisbecomingbloated(self): pass
def almostattheendoftheclass(self): pass
def imgonnahaveacouplemore(self): pass
def somanymethodssssss(self): pass
def should_i_add_more(self): pass
def yes_just_a_couple(self): pass
def just_for_lolz(self): pass
def coming_up_with_good_method_names_is_hard(self): pass
Результаты, достижения:
>>> call_1000000_times(dict)
0.2680389881134033
>>> call_1000000_times(X)
0.6771988868713379
>>> call_1000000_times(Y)
0.6260080337524414
Как видите, разница между большим классом и небольшим классом очень мала, и в этом случае большой класс даже быстрее. Я предполагаю, что если бы вы запускали эту функцию несколько раз с одним и тем же типом и усредняли числа, они были бы еще ближе, но сейчас уже 3 часа ночи, и мне нужно поспать, поэтому я не собираюсь устанавливать это прямо сейчас.
С другой стороны, просто звоню dict
был примерно в 2,5 раза быстрее, поэтому, если ваше узкое место - инстанцирование, это может быть местом для оптимизации вещей.
Однако будьте осторожны с преждевременной оптимизацией. Классы, объединяя данные и код, могут сделать ваш код более легким для понимания и построения (любители функционального программирования, это не место для спора). Было бы неплохо использовать профилировщик Python или другие инструменты измерения производительности, чтобы узнать, какие части вашего кода замедляют его.