A faster alternative to namedtuple.
importplain_objConfig=plain_obj.new_type('Config', 'is_debug, skips_dist, run_tests')
config=Config(True, False, True)
ifconfig.is_debug:
print("This is a verbose debugging message.")config.as_dict()is_debug, _, run_tests=configWhen faster creation time matters to you.
Comparing plain_obj with namedtuple in Python 2.7:
In [3]: %timeitcollections.namedtuple('Point', ['x', 'y', 'z'])
1000loops, bestof3: 338µsperloopIn [4]: %timeitplain_obj.new_type('Point', ['x', 'y', 'z'])
10000loops, bestof3: 97.8µsperloopIn [5]: Point=collections.namedtuple('Point', ['x', 'y', 'z'])
In [6]: NewPoint=plain_obj.new_type('Point', ['x', 'y', 'z'])
In [7]: %timeitPoint(1, 2, 3)
Theslowestruntook7.99timeslongerthanthefastest. Thiscouldmeanthatanintermediateresultisbeingcached.
1000000loops, bestof3: 507nsperloopIn [8]: %timeitNewPoint(1, 2, 3)
Theslowestruntook6.70timeslongerthanthefastest. Thiscouldmeanthatanintermediateresultisbeingcached.
1000000loops, bestof3: 462nsperloopIn [9]: p=Point(1, 2, 3)
In [10]: new_p=NewPoint(1, 2, 3)
In [11]: %timeitp.x, p.y, p.zTheslowestruntook9.92timeslongerthanthefastest. Thiscouldmeanthatanintermediateresultisbeingcached.
1000000loops, bestof3: 408nsperloopIn [12]: %timeitnew_p.x, new_p.y, new_p.zTheslowestruntook11.70timeslongerthanthefastest. Thiscouldmeanthatanintermediateresultisbeingcached.
10000000loops, bestof3: 163nsperloopComparing plain_obj with namedtuple in Python 3.6:
In [3]: %timeitcollections.namedtuple('Point', ['x', 'y', 'z'])
382µs ± 3.82µsperloop (mean ± std. dev. of7runs, 1000loopseach)
In [4]: %timeitplain_obj.new_type('Point', ['x', 'y', 'z'])
53.5µs ± 1.2µsperloop (mean ± std. dev. of7runs, 10000loopseach)
In [5]: Point=collections.namedtuple('Point', ['x', 'y', 'z'])
In [6]: NewPoint=plain_obj.new_type('Point', ['x', 'y', 'z'])
In [7]: %timeitPoint(1, 2, 3)
521ns ± 2.5nsperloop (mean ± std. dev. of7runs, 1000000loopseach)
In [8]: %timeitNewPoint(1, 2, 3)
438ns ± 5.53nsperloop (mean ± std. dev. of7runs, 1000000loopseach)
In [9]: p=Point(1, 2, 3)
In [10]: new_p=NewPoint(1, 2, 3)
In [11]: %timeitp.x, p.y, p.z282ns ± 2.52nsperloop (mean ± std. dev. of7runs, 1000000loopseach)
In [12]: %timeitnew_p.x, new_p.y, new_p.z148ns ± 1.7nsperloop (mean ± std. dev. of7runs, 10000000loopseach)As you can see, it's faster in all cases including type creation, object instantiation and attribute access.