Profile picture
, 19 tweets, 5 min read Read on Twitter
Let's talk about immutability. Python, unlike languages like Clojure, Erlang, and Rust is built entirely around mutable state. I'm going to try to convince you that immutability is awesome and can be effectively used in Python today.

Thread 👇
1. If an object is immutable it means that its state cannot be changed after it is created. For instance, in Python you can't change a character in a string, or reassign an element of a tuple. Python ships with a few immutable datatypes: str, bytes, tuple/namedtuple, frozenset.
2. Users can of course create their own immutable datatypes / objects. If an object doesn't have API to mutate its state and all of its public attrubutes are exposed via a readonly @property it is effectively immutable.
3. Immutable objects are special because that can be "hashable". That means that they implement a __hash__() method, which, in turn, means that they can be keys in dicts and other mappings.
4. It's not safe to make a mutable object hashable. Imagine a dictionary key that isn't stable and can be changed at any time! Thus immutability and hashability are closely related things.
5. That said, it's possible for an immutable collection to be non-hashable. Hashing is a recursive operation, so If an immutable collection contains a mutable object, it becomes non-hashable.
6. Hashable & immutable objects and collections can be used as cache keys. Therefore functions that receive only immutable arguments and have no side effects can be decorated with @functools.lru_cache to speed things up!
7. Immutable objects are so easy to reason about; you can cache them & pass them around safely. For example, "inspect.signature()" function returns a Signature object. It has a lot of metadata, all of which is immutable. So it's cached and computed only once per a function!
8a. Another great examples is the new 'contextvars' stdlib module. Context Variables are similar to threadlocal objects, and are used to have local state in async/await code. How can we implement this local state and make it super fast to capture the state?
8b. The answer, of course, is to make it immutable! contextvars store all their state in an immutable collection, so to capture the entire local state you only need to assign it to a variable! Any change to the state creates a new version of the state.
8c. We use the same concept in @edgedatabase, where the schema of the database is stored in an immutable collection. It means that implementing support for transactions, savepoints, and DDL is easy.
9. Unfortunately Python doesn't have an immutable mapping datatype yet. There's a trick though: types.MappingProxyType. Wrap a dict with it and return it from your API. Without access to the wrapped dict it's impossible to mutate the MappingProxy:
10. So types.MappingProxyType can be used to expose a read-only dict and that's great. Sadly it's not hashable though, so it can't be used as a cached key etc. There's a solution though. The above mentioned contextvars module required an efficient immutable mapping type.
11. The implementation of that new mapping type is rather complex, and it would be a shame if we could only use it for contextvars and nothing else. So we created a new library out of it: immutables. github.com/magicstack/imm…
12. With immutables.Map you can easily create immutable and hashable mappings. The Map type is almost as fast as Python dict, with O(log32 N) lookup/update complexity. Maybe we'll have it in Python 3.8 stdlib!
13. BTW, there's a new trick to easily declare named tuples in Python: typing.NamedTuple. I use it all the time.
14. Similar to (13), you can also create a frozen dataclass:
This thread sums up pretty much everything I know about immutability in Python. Don't forget to scroll up :) 👆
15. Bonus. Did you know about namedtuple._replace() method?
Missing some Tweet in this thread?
You can try to force a refresh.

Like this thread? Get email updates or save it to PDF!

Subscribe to Yury Selivanov
Profile picture

Get real-time email alerts when new unrolls are available from this author!

This content may be removed anytime!

Twitter may remove this content at anytime, convert it as a PDF, save and print for later use!

Try unrolling a thread yourself!

how to unroll video

1) Follow Thread Reader App on Twitter so you can easily mention us!

2) Go to a Twitter thread (series of Tweets by the same owner) and mention us with a keyword "unroll" @threadreaderapp unroll

You can practice here first or read more on our help page!

Follow Us on Twitter!

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just three indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3.00/month or $30.00/year) and get exclusive features!

Become Premium

Too expensive? Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal Become our Patreon

Thank you for your support!