Вы не можете сделать это намного быстрее, но я бы определенно использовал __slots__
, чтобы сэкономить на распределении памяти. Также сделайте возможным передать значения атрибута при создании экземпляра:
class Edge:
__slots__ = ('node1', 'node2', 'weight')
def __init__(self, node1=0, node2=0, weight=0):
self.node1 = node1
self.node2 = node2
self.weight = weight
С обновленным __init__
вы можете использовать понимание списка:
edges = [Edge(*args) for args in ijw]
Вместе они могут сэкономить приличное количество времени на создание объектов, примерно вдвое сократить необходимое время.
Сравнение создания 1 миллиона объектов; настройка:
>>> from random import randrange
>>> ijw = [(randrange(100), randrange(100), randrange(1000)) for _ in range(10 ** 6)]
>>> class OrigEdge:
... def __init__(self):
... self.node1 = 0
... self.node2 = 0
... self.weight = 0
...
>>> origloop = '''\
... edges= []
... for (i,j,w) in ijw:
... edge = Edge()
... edge.node1 = i
... edge.node2 = j
... edge.weight = w
... edges.append(edge)
... '''
>>> class SlotsEdge:
... __slots__ = ('node1', 'node2', 'weight')
... def __init__(self, node1=0, node2=0, weight=0):
... self.node1 = node1
... self.node2 = node2
... self.weight = weight
...
>>> listcomploop = '''[Edge(*args) for args in ijw]'''
и время:
>>> from timeit import Timer
>>> count, total = Timer(origloop, 'from __main__ import OrigEdge as Edge, ijw').autorange()
>>> (total / count) * 1000 # milliseconds
722.1121070033405
>>> count, total = Timer(listcomploop, 'from __main__ import SlotsEdge as Edge, ijw').autorange()
>>> (total / count) * 1000 # milliseconds
386.6706900007557
Это почти в 2 раза быстрее.
Увеличение списка случайных входов до 10 ^ 7 элементов, и разница во времени сохраняется:
>>> ijw = [(randrange(100), randrange(100), randrange(1000)) for _ in range(10 ** 7)]
>>> count, total = Timer(origloop, 'from __main__ import OrigEdge as Edge, ijw').autorange()
>>> (total / count)
7.183759553998243
>>> count, total = Timer(listcomploop, 'from __main__ import SlotsEdge as Edge, ijw').autorange()
>>> (total / count)
3.8709938440006226