Skip to main content

No project description provided

Project description

Python is inherently mutable, only a handful of builtin classes enjoy true immutability such as int, str, and tuple; everything else is up for grabs. This allows a lot of clever tricks, but it also leads to some difficult bugs. Just think about code like this:

class MyClass:

    def __init__(self) -> None:
        self._mylist: List[str] = []

    def get_mylist(self) -> List[str]:
        return self._mylist

What happens when someone gets that list and mutates it? Of course, you get bugs because MyClass now has something it doesn’t expect. The easiest way to fix that is of course to do this:

class MyClass:

    def __init__(self) -> None:
        self._mylist: List[str] = []

    def get_mylist(self) -> List[str]:
        return self._mylist.copy()

Problem solved, right? What if _mylist has a million entires? That can quickly become a huge bottle neck in your program. In most statically typed languages you have some kind of “const” or “immutable” modifier that tells the compiler/interpreter “don’t let anyone modify this”. Normally that would be impossible in python, but we have static type checkers like mypy, and Protocols. We can create a protocol that implements all of the methods that don’t mutate a class, and expose only those. Then the static type checker can catch the mutation for us.

from constprotocol import ConstList

class MyClass:

    def __init__(self) -> None:
        self._mylist: List[str] = []

    def get_mylist(self) -> ConstList[str]:
        return self._mylist

c = MyClass()
c.get_mylist().append('foo')  # Error: ConstList has not method append!

Of course, the underlying python values have not actually become immutable, but like C and C++ it’s more of a promise that if you take a ConstList or return one that you’re not going to modify it.

One of the goals of const protocol is to have 0 runtime performance impact. You could create an immutable proxy, that wraps a value and only exposes it’s const methods, and all of it’s attributes as read only (using properties and more proxies). But that has runtime overhead and adds code complexity. This approach adds zero run time overhead and very little complexity to the code.

What if I want to mutate the value after all?

You don’t.

No seriously, if you say you’re not going to modify it, don’t.

What you probably want to do is copy the constified value, which will give you a mutable value:

l: ConstList[str] = ['a', 'b', 'c']
ml = l.copy()
reveal_type(ml)

Which will be List[str]

If you really, really, need to, you can use typing.cast. of course, you get to keep the pieces.

Status

Right now there are four classes ConstSet for set, ConstList for list, ConstMapping for mappings, and ContDict for Dict. There’s likely bugs, this is alpha quality software, and a kind of crazy idea to get better error checking in cases where the author knows that someone shouldn’t be mutating their data.

I found a bug

Cool, file an issue.

I want fix something or add something

Even better, open a Merge Request

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

constprotocol-0.0.1.tar.gz (10.0 kB view details)

Uploaded Source

Built Distribution

constprotocol-0.0.1-py3-none-any.whl (10.5 kB view details)

Uploaded Python 3

File details

Details for the file constprotocol-0.0.1.tar.gz.

File metadata

  • Download URL: constprotocol-0.0.1.tar.gz
  • Upload date:
  • Size: 10.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/46.4.0 requests-toolbelt/0.9.1 tqdm/4.48.2 CPython/3.8.6

File hashes

Hashes for constprotocol-0.0.1.tar.gz
Algorithm Hash digest
SHA256 96defd88b8f0fb83619bd194df8043a1802fa35c8fac007bfde0d6c6eea81884
MD5 5998b33e2a3163cbcc3736e9f3c66faf
BLAKE2b-256 05146cb4f98dd79fe945c69c14a5f0221429fda8b39064b5c8003ffebe1f9cf4

See more details on using hashes here.

File details

Details for the file constprotocol-0.0.1-py3-none-any.whl.

File metadata

  • Download URL: constprotocol-0.0.1-py3-none-any.whl
  • Upload date:
  • Size: 10.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/46.4.0 requests-toolbelt/0.9.1 tqdm/4.48.2 CPython/3.8.6

File hashes

Hashes for constprotocol-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 77f47e4f1051c51819c159ab977358682a091197cf9ba0cc61e913c70bd0398d
MD5 3554457310fbac3eb184a7836896b001
BLAKE2b-256 765e5da42ebb68ea58de45921f71eda416c39f44d31320648403edefd9862819

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page