Performance Comparison of namedtuple, namedlist, and recordclass
import sys | |
class Record(object): | |
__slots__ = () | |
def __init__(self, *args): | |
assert len(self.__slots__) == len(args) | |
for field, value in zip(self.__slots__, args): | |
setattr(self, field, value) | |
def __getitem__(self, index): | |
return getattr(self, self.__slots__[index]) | |
def __len__(self): | |
return len(self.__slots__) | |
def __eq__(self, that): | |
if not isinstance(that, type(self)): | |
return NotImplemented | |
return all(item == iota for item, iota in zip(self, that)) | |
def __repr__(self): | |
args = ', '.join(repr(item) for item in self) | |
return '%s(%s)' % (type(self).__name__, args) | |
def __getstate__(self): | |
return tuple(self) | |
def __setstate__(self, state): | |
self.__init__(*state) | |
from collections import namedtuple | |
from namedlist import namedlist | |
from recordclass import recordclass | |
NTTest = namedtuple('NTTest', 'a b c d e f') | |
NLTest = namedlist('NLTest', 'a b c d e f') | |
RCTest = recordclass('RCTest', 'a b c d e f') | |
class RETest(Record): | |
__slots__ = 'a', 'b', 'c', 'd', 'e', 'f' | |
nttest = NTTest(1, 2, 3, 4, 5, 6) | |
nltest = NLTest(1, 2, 3, 4, 5, 6) | |
rctest = RCTest(1, 2, 3, 4, 5, 6) | |
retest = RETest(1, 2, 3, 4, 5, 6) | |
print 'Attribute Access' | |
print 'namedtuple' | |
%timeit nttest.c | |
print 'namedlist' | |
%timeit nltest.c | |
print 'recordclass' | |
%timeit rctest.c | |
print 'Record' | |
%timeit retest.c | |
print 'Object Size' | |
print 'namedtuple' | |
print sys.getsizeof(nttest) | |
print 'namedlist' | |
print sys.getsizeof(nltest) | |
print 'recordclass' | |
print sys.getsizeof(rctest) | |
print 'Record' | |
print sys.getsizeof(retest) |
This comment has been minimized.
This comment has been minimized.
#python 3.7
import sys
from lib import exec_time # based on get min time of timeit.Timer and partial().repeat()
from collections import namedtuple
from namedlist import namedlist
from recordclass import recordclass, structclass
class Record(object):
__slots__ = ()
def __init__(self, *args):
assert len(self.__slots__) == len(args)
for field, value in zip(self.__slots__, args):
setattr(self, field, value)
def __getitem__(self, index):
return getattr(self, self.__slots__[index])
def __len__(self):
return len(self.__slots__)
def __eq__(self, that):
if not isinstance(that, type(self)):
return NotImplemented
return all(item == iota for item, iota in zip(self, that))
def __repr__(self):
args = ', '.join(repr(item) for item in self)
return '%s(%s)' % (type(self).__name__, args)
def __getstate__(self):
return tuple(self)
def __setstate__(self, state):
self.__init__(*state)
params_count = 6
fields = tuple(hex(_)[1:] for _ in range(params_count))
args = tuple(range(params_count))
NTTest = namedtuple('NTTest', fields)
NLTest = namedlist('NLTest', fields)
RCTest = recordclass('RCTest', fields)
SCTest = structclass('SCTest', fields)
class RETest(Record):
__slots__ = fields
print('\nCreate:')
print(f'\tnamedtuple: {exec_time(NTTest, *args)}')
print(f'\tnamedlist: {exec_time(NLTest, *args)}')
print(f'\trecordclass: {exec_time(RCTest, *args)}')
print(f'\tstructclass: {exec_time(SCTest, *args)}')
print(f'\tRecord: {exec_time(RETest, *args)}')
nttest = NTTest(*args)
nltest = NLTest(*args)
rctest = RCTest(*args)
sctest = SCTest(*args)
retest = RETest(*args)
print('\nAccess:')
print(f'\tnamedtuple: {exec_time(lambda: nttest.x1)}')
print(f'\tnamedlist: {exec_time(lambda: nltest.x1)}')
print(f'\trecordclass: {exec_time(lambda: rctest.x1)}')
print(f'\tstructclass: {exec_time(lambda: sctest.x1)}')
print(f'\tRecord: {exec_time(lambda: retest.x1)}')
print('\nSize:')
print(f'\tnamedtuple: {sys.getsizeof(nttest)}')
print(f'\tnamedlist: {sys.getsizeof(nltest)}')
print(f'\trecordclass: {sys.getsizeof(rctest)}')
print(f'\tstructclass: {sys.getsizeof(sctest)}')
print(f'\tRecord: {sys.getsizeof(retest)}')
|
This comment has been minimized.
This comment has been minimized.
print('\nAccess:')
print(f'\tnamedtuple: {exec_time(lambda: (nttest.x0, nttest.x1, nttest.x2, nttest.x3, nttest.x4, nttest.x5))}')
print(f'\tnamedlist: {exec_time(lambda: (nltest.x0, nltest.x1, nltest.x2, nltest.x3, nltest.x4, nltest.x5))}')
print(f'\trecordclass: {exec_time(lambda: (rctest.x0, rctest.x1, rctest.x2, rctest.x3, rctest.x4, rctest.x5))}')
print(f'\tstructclass: {exec_time(lambda: (sctest.x0, sctest.x1, sctest.x2, sctest.x3, sctest.x4, sctest.x5))}')
print(f'\tRecord: {exec_time(lambda: (retest.x0, retest.x1, retest.x2, retest.x3, retest.x4, retest.x5))}')
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
Output:
My advice is to prefer the
Record
recipe above. Thirty lines of code and it pretty prints, pickles, copies, and unpacks. You can also easily customize to your liking.