跳转到主要内容

未提供项目描述

项目描述

Python本身是可变的,只有少数内建类如 intstrtuple 具有真正的不可变性;其他一切都可以被修改。这允许进行很多巧妙的操作,但同时也可能导致一些难以解决的bug。想想看这样的代码

class MyClass:

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

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

当有人获取这个列表并修改它时会发生什么?当然,你会得到bug,因为MyClass现在有了它不应该有的东西。当然,解决这个问题的最简单方法是这样做

class MyClass:

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

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

问题解决了,对吧?如果_mylist有一百万条条目怎么办?这可能会迅速成为你程序的一个巨大瓶颈。在大多数静态类型语言中,你有一些“const”或“immutable”修饰符,告诉编译器/解释器“不要修改这个”。在Python中通常这是不可能的,但我们有像mypy和Protocols这样的静态类型检查器。我们可以创建一个协议,实现所有不修改类的函数,并只暴露这些。然后静态类型检查器可以帮我们捕获修改。

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!

当然,底层Python值实际上并没有变得不可变,但就像C和C++一样,它更像是一个承诺,如果你拿一个ConstList或返回一个,你就不会修改它。

const 协议的一个目标是在运行时没有性能影响。你可以创建一个不可变代理,它封装一个值,仅公开其 const 方法,并将所有属性作为只读(使用属性和更多代理)。但这会增加运行时开销,并增加代码复杂性。这种方法在代码中几乎不增加运行时开销和复杂性。

如果我之后想修改这个值怎么办呢?

你不。

认真地说,如果你说你不会修改它,那就不要。

你可能想复制这个 const 化的值,这将给你一个可变值

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

它将是 List[str]

如果你真的,真的需要,你可以使用 typing.cast。当然,你可以保留这些部分。

状态

目前有四个类 ConstSet 用于 setConstList 用于 listConstMapping 用于 mappings,以及 ContDict 用于 Dict。可能存在错误,这是alpha质量的软件,而且这是一个疯狂的想法,目的是在作者知道某人不应该修改其数据的情况下获得更好的错误检查。

我发现了一个错误

很好,提交一个问题。

我想修复某个东西或添加某个东西

更好的是,发起一个合并请求

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于 安装软件包 的信息。

源代码分发

constprotocol-0.0.1.tar.gz (10.0 kB 查看哈希值)

上传时间 源代码

构建分发

constprotocol-0.0.1-py3-none-any.whl (10.5 kB 查看哈希值)

上传时间 Python 3

支持者

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面