In [4]:
import attr
import time
from collections import namedtuple
from tabulate import tabulate

TRIALS = 1000000

@attr.s
class PointAttr:
    x = attr.ib()
    y = attr.ib()
    
PointNamedTuple = namedtuple("PointNamedTuple", ["x", "y"])

class PointClass:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        
def benchmark_attrs():
    attr_instance = PointAttr(x=1, y=2)
    assert attr_instance.x == 1
    
def benchmark_class():
    class_instance = PointClass(x=1, y=2)
    assert class_instance.x == 1
    
def benchmark_namedtuple():
    namedtuple_instance = PointNamedTuple(x=1, y=2)
    assert namedtuple_instance.x == 1
    
def benchmark_namedtuple_index_access():
    namedtuple_instance = PointNamedTuple(x=1, y=2)
    assert namedtuple_instance[0] == 1
    
def benchmark_dict():
    dict_instance = {"x": 1, "y": 2}
    assert dict_instance["x"] == 1
    
def benchmark_tuple():
    tuple_instance = (1, 2)
    assert tuple_instance[0] == 1
        
def benchmark(name, func):
    start_time = time.time()
    for i in range(TRIALS):
        func()
    elapsed_time = time.time() - start_time
    return [name, elapsed_time, TRIALS]
        
data = [["library", "execution_time (seconds)", "iterations"]]
data.append(benchmark("attrs", benchmark_attrs))
data.append(benchmark("class", benchmark_class))
data.append(benchmark("namedtuple", benchmark_namedtuple))
data.append(benchmark("namedtuple", benchmark_namedtuple_index_access))
data.append(benchmark("tuple", benchmark_tuple))
data.append(benchmark("dict", benchmark_dict))
print(tabulate(data, headers="firstrow"))
library       execution_time (seconds)    iterations
----------  --------------------------  ------------
attrs                         0.817883       1000000
class                         0.807761       1000000
namedtuple                    0.851075       1000000
namedtuple                    0.828901       1000000
tuple                         0.149515       1000000
dict                          0.221976       1000000