Laurent Luce
laurentluce.com · Personal blog · on HN since 2011
Laurent Luce writes about Python internals and tools, covering dictionary, list, and integer implementations, concurrency primitives, and Twitter sentiment analysis.
What HN saysHN links it to explain how CPython implements lists and small integers, such as why small integers are preallocated.
22HN people shared it
8linked it in comments
16stories submitted
156story points
4 years agolast shared
2011people per year2026
Most-shared posts
- 1Python Dictionary Implementation6 people · 5 points · first shared 2013 · discussion on HN
- 2Twitter sentiment analysis using Python and NLTK3 people · 85 points · first shared 2012 · 8 comments on HN
- 3Solving mazes using Python: Simple recursivity and A* search2 people · 16 points · first shared 2011 · 7 comments on HN
- 4Python String Objects Implementation2 people · 2 points · first shared 2016 · discussion on HN
- 5Python integer objects implementation2 people · first shared 2014
- 6Python list implementation2 people · first shared 2016
- 7Python Locks, RLocks, Semaphores, Conditions, Events and Queues1 people · 33 points · first shared 2011 · 4 comments on HN
- 8Python’s dictionary implementation1 people · 8 points · first shared 2011 · discussion on HN
- 9Python’s list implementation1 people · 3 points · first shared 2011 · discussion on HN
- 10Create a Debian package for your Django application (2010)1 people · 1 points · first shared 2016 · discussion on HN
- 11Geo data of the Massachusetts elementary school districts using Python1 people · 1 points · first shared 2013 · discussion on HN
- 12Python and cryptography with pycrypto1 people · 1 points · first shared 2014 · discussion on HN
- 13Python, Twitter statistics and the 2012 French presidential election1 people · 1 points · first shared 2012 · discussion on HN
What HN people wrote when they linked it
e12e · 2019-12-21
Since there isn't any traversal when looking up an element n, I guess the best "short hand" would be to call it an array - it's an array of pointers to objects on the heap.
https://www.laurentluce.com/posts/python-list-implementation/
As for collections within collections, python allows for that in "lists" (arrays) and "dictionaries" (maps).
photochemsyn · 2022-10-09
These kinds of diagrams are OK for the most basic introduction to data structures, but they're not much help when it comes to creating an efficient implementation. Learning about data structure implementation without using a relatively low-level language that allows pointers seems to be a recipe for confusion.
Hence, one is probably always better off using the built-ins or libraries for any data structure in a higher-level language rather than implementing them from scratch. For example, here's a nice blog post on how Python dicts are implemented using hash tables written in C.
https://www.laurentluce.com/posts/python-dictionary-implementation/
While it's possible to build something like a binary search tree from scratch in Python using classes for nodes and with references instead of pointers, along with recursive algorithms for traversing it, it doesn't seem like that great of an idea to teach students in this manner. If the goal is to really teach students how to do this, C or similar (Rust?) is probably the better option for code examples, and a lot of time would have to be spent on memory management concepts (i.e. have students build their own dynamically allocated stack for the traversal, to avoid blowing through the stack, maybe).
gtirloni · 2018-01-24
It's puzzling that "x is 17" should work but then "1000 + 1 is 1001" doesn't.
The reason is that Python pre-allocates 262 numbers at initialization (-5 to 256) and the allocation uses a different method/structure for bigger numbers.
>>> x = 256
>>> x is 256
True
>>> id(x)
94900419138400
>>> id(256)
94900419138400
>>> x = 257
>>> x is 257
False
>>> id(x)
94900419504344
>>> id(257)
94900419504368
Reference: https://www.laurentluce.com/posts/python-integer-objects-implementatio…
denfromufa · 2016-07-29
Here is blog post about python list implementation, one of 2 main data structures used internally: http://www.laurentluce.com/posts/python-list-implementation/
ForHackernews · 2014-05-09
Python statically allocates small integers (-5 to 256), so you're not actually creating a new object unless you're creating one outside that range.
http://www.laurentluce.com/posts/python-integer-objects-implementation…
bcjordan · 2014-01-03
Raw source: http://svn.python.org/view/%2acheckout%2a/python/tags/r266/Objects/dic…
Walkthrough of the implementation: http://www.laurentluce.com/posts/python-dictionary-implementation/
fencepost · 2017-09-10
So likely thinking of it in terms of checking a tree based on characters instead of hashes of full words. Which is more viable would likely depend on what kind of memory constraints and dictionary size was being considered. Also very implementation dependent, what's the size of the hashes generated?
Edit: curiosity got me looking at this for Python, with an answer of "it depends, and both have correct aspects" based on Python's implementation [1]. The hashing varies by string length, the lookup is fixed unless there's a collision and probing, probing will be minimized by growing the dictionary as items are added. In any case, better than O(n) but worse than O(1) and with some possible slowdowns during loading unless you can set an expected final size during initialization.
Edit again: since I brought it up, turns out initialization doesn't really matter, resizing is not a speed factor. Relevant discussion starts from https://stackoverflow.com/questions/1298636/how-to-set-initial-size-fo…
[1] http://www.laurentluce.com/posts/python-dictionary-implementation/
iheartmemcache · 2016-07-28
My gut-ballpark was going to be around an order of magnitude, not two. Here's are two naive comparisons (granted, from the late aughts and not a direct comparison but a more general one) that show ~7-8x[0,1]. The overhead of PyStringObject is not trivial[2] (though the implementation details likely have changed between Py2.x and Python 3).
For things like building accumulators a set of data/log parsing rather than data munging (hits per hour or enumerative tasks), I'd imagine (g|n)?awk might hit your 100x since you'd just grab the fd and traverse being IO bound. I'm not sure how awk does it, but if it's just saving an accumulator value (or 10) in a register. Assuming x64-64 treats, say, an r3 fetch analogously to a fetch to ecx (err..rcx now I guess), rather than having to keep a full object in L1 cache, awk has a huge advantage.
---
N.b., if you're benching tasks like this, don't use 'time' and STDOUT and think you're getting real performance numbers. Your bottleneck (terminals can only render $x lines a minute, so the kernel call to write(STDOUT, ....) will be where you choke, not at the language. Also disk fragmentation would be another issue. Put the both the test file and the output file on a RAMdisk.) Cache flush with Something like sync; echo 3 > /proc/sys/vm/drop_caches (on Linux, I forget the BSD way of doing it) then `time benchmark.py /mnt/ramdisk1/file > /mnt/ramdisk2' over multiple runs, under various loads, with different data sets, etc
Another interesting…