In the sense of Java and C ++, class member references are fast and map references are slow, but this is not always the case with Python. This is because Python treats class as a kind of dict internally, so even if you simply use dict in normal usage, it will not be so disadvantageous in terms of speed [^ 1].
[^ 1]: Since it was pointed out that it was necessary to measure the memory allocation and reference time separately, some measurement items were corrected. Part of the content has been changed accordingly.
Validation script
import collections
import random
import time
#
#Implemented in class.
#
class EClass:
def __init__(self, x, y):
self.x = x
self.y = y
def test_class(n):
l = []
t1 = time.time()
for _ in range(n):
x = random.random()
y = random.random()
e = EClass(x, y)
l.append(e)
t2 = time.time()
for e in l:
x = e.x
y = e.y
z = x + y
t3 = time.time()
return (t1, t2, t3)
#
#Implemented in class (with slots).
#
class EClassSlot:
__slots__ = ["x", "y"]
def __init__(self, x, y):
self.x = x
self.y = y
def test_class_slot(n):
l = []
t1 = time.time()
for _ in range(n):
x = random.random()
y = random.random()
e = EClassSlot(x, y)
l.append(e)
t2 = time.time()
for e in l:
x = e.x
y = e.y
z = x + y
t3 = time.time()
return (t1, t2, t3)
#
#Implemented with dict.
#
def test_dict(n):
l = []
t1 = time.time()
for _ in range(n):
x = random.random()
y = random.random()
e = {"x": x, "y": y}
l.append(e)
t2 = time.time()
for e in l:
x = e["x"]
y = e["y"]
z = x + y
t3 = time.time()
return (t1, t2, t3)
#
#Implemented with list.
#
def test_list(n):
l = []
t1 = time.time()
for _ in range(n):
x = random.random()
y = random.random()
e = [x, y]
l.append(e)
t2 = time.time()
for e in l:
x = e[0]
y = e[1]
z = x + y
t3 = time.time()
return (t1, t2, t3)
#
#Implemented with tuple.
#
def test_tuple(n):
l = []
t1 = time.time()
for _ in range(n):
x = random.random()
y = random.random()
e = ((x, y, None))
l.append(e)
t2 = time.time()
for i, e in enumerate(l):
x = e[0]
y = e[1]
z = x + y
t3 = time.time()
return (t1, t2, t3)
#
#Implemented with namedtuple.
#
ENamedTuple = collections.namedtuple("E", ("x", "y"))
def test_namedtuple(n):
l = []
t1 = time.time()
for _ in range(n):
x = random.random()
y = random.random()
e = ENamedTuple(x, y)
l.append(e)
t2 = time.time()
for i, e in enumerate(l):
x = e.x
y = e.y
z = x + y
t3 = time.time()
return (t1, t2, t3)
#
#Conduct a test.
#
tests = [
("class\t", test_class),
("class_slot", test_class_slot),
("dict\t", test_dict),
("list\t", test_list),
("tuple\t", test_tuple),
("namedtuple", test_namedtuple)
]
n = 5000000
print("test\t\talloc\trefer\ttotal")
for test, function in tests:
t1, t2, t3 = function(n)
print("%s\t%0.2f\t%0.2f\t%0.2f"
%(test, t2 - t1, t3 - t2, t3 - t1))
The results are shown below, and when focusing on the time required for the reference operation, it can be seen that the implementation using dict is not much different from the implementation using normal class. If you use slot, you can access it a little faster than dict, but object generation takes almost twice as long as dict and list, so if you consider including the time it takes to secure elements, this difference is about this. It becomes an almost meaningless number.
Execution result
test alloc refer total
class 7.68 0.84 8.52
class_slot 6.41 0.76 7.17
dict 3.64 0.79 4.43
list 4.00 0.72 4.72
tuple 2.41 0.96 3.37
namedtuple 7.50 1.70 9.20
Although list is the fastest for reference operations, there is no reason to use it for the above purposes, considering the time and effort required to specify an element as an index. In fact, the tuple I was secretly expecting turned out not to be so fast in terms of reference speed. However, it is the fastest to secure the elements, and considering that the values cannot be changed after creation, it can be said that it is sufficient for exchanging small values.
namedtuple is very slow to generate and reference. This is because namedtuple searches for members in order from the beginning each time, and although memory efficiency is good, the speed becomes slower as the number of elements increases.
Recommended Posts