4 ms·
Besides immutability, what are the advantages of using namedtuples instead of dicts?
by erokar 10y ago
Besides immutability, what are the advantages of using namedtuples instead of dicts?
- burntsushi 10y ago- A clear single point of truth describing your data. - Probably more memory efficient.
- i80and 10y agoWe can test memory usage in CPython (3.5)! >>> import collections >>> import sys >>> class A: ... def __init__(self, x, y): ... self.x = x ... self.y = y ... >>> class B: ... __slots__ = ('x', 'y') ... def __init__(self, x, y): ... self.x = x ... self.y = y ... >>> C = collections.namedtuple('C', ('x', 'y')) >>> a = A(1, 1) >>> b = B(1, 1) >>> c = C(1, 1) >>> d = {'x': 1, 'y': 1} >>> sys.getsizeof(a) + sys.getsizeof(a.__dict__) # Plain object 344 >>> sys.getsizeof(b) + sys.getsizeof(b.__slots__) # Plain object with slots 120 >>> sys.getsizeof(c) # Named Tuple 64 >>> sys.getsizeof(d) # Dict 288 EDIT: Fixed a slew of measurement issues EDIT2: Included size of __slots__ tuple
- SEJeff 10y agoIf you're using Python 3.5, use tracemalloc, it is much nicer for this sort of thing. https://docs.python.org/3/library/tracemalloc.html https://docs.python.org/3/library/tracemalloc.html
- lqdc13 10y agoIt is an order of magnitude slower and not less memory efficient. Also, for me it is never easier to understand what is going on when named tuples are used instead of dicts Proof: def make_dicts(): res = [] for i in range(1000000): res.append({'x': i, 'y': i}) return res def make_tuples(): templ = namedtuple('Point', ('x', 'y')) res = [] for i in range(1000000): res.append(templ(i, i)) return res from ipython_memory_usage import ipython_memory_usage as imu imu.start_watching_memory() used 0.2305 MiB RAM in 4.00s, peaked 0.00 MiB above current, total RAM usage 86.41 MiB %time tuples = make_tuples() CPU times: user 780 ms, sys: 32 ms, total: 812 ms Wall time: 816 ms used 109.0625 MiB RAM in 0.92s, peaked 0.00 MiB above current, total RAM usage 195.47 MiB %time dicts = make_dicts() CPU times: user 160 ms, sys: 32 ms, total: 192 ms Wall time: 194 ms used 99.5117 MiB RAM in 0.30s, peaked 0.00 MiB above current, total RAM usage 524.33 MiB
- burntsushi 10y agoYour sibling got opposite results. I haven't dissected either program, but I don't see any obvious flaws. I find your results particularly surprising. Can you explain them? Are there optimisations going on in your benchmark that you haven't accounted for? It should not be controversial that namedtuples are clearer for the reason I stated in my initial comment.
- lqdc13 10y agosys.getsizeof() on a code object returns the size of the code struct, not all the other objects it references. To measure real usage, you have to use another method. I use ipython_memory_usage because it's easy to use. You can test this out easily by making a large dict and see how much your OS thinks python is using vs what sys.getsizeof is reporting.
- mixmastamyk 10y ago- Dot syntax: foo.length rather than foo['length']
- lgunsch 10y agoI gives a name and expected properties to common data structures, or unspoken unnamed types. Many times when a dict is used, it's expected to have certain attributes, and may have expected ways of interacting with those attributes. Named tuples is a simple way to formalize these, which makes them not so mysterious to you future-you, or to other developers who inherit the project 6 months down the road.