* Flattening data from hierarchical, custom types into flatter, builtin collection types can make a speed difference. The builtin type methods spend more time in the native code and are optimized.
* Lots of things that I thought could make a difference but would barely move the needle. There is so much pointer indirection internal to CPython.
* The set and frozenset types can offer easy and immediate algorithmic improvements. This is obvious from a formal/academic perspective but continues to be my favorite thing about writing quick and dirty python. I have encountered cases where an algorithm called for a fancy data structure but doing simple set intersection and difference was good enough.
* Over time, Python taught me to worry less about optimizing things that didn't matter. Everyone pays lip service to the perils of premature optimization but I think there are layers to the problem. Fast languages make many affordances for optimization, and to some extent compel you to make detailed choices that have performance implications (e.g. choice of integer width, choice of collection type). There is something very liberating about reminding myself "it's going to be slow either way, and it doesn't matter." When I work in Swift for example I find myself getting distracted by finer details that relates to efficiency.