18

我欣赏 Python 的一件事是它区分了可变类型和不可变类型。在开始使用 Python 之前在 c 中进行了一段时间的编程后,我惊讶于 Python 如此轻松地消除了指针取消引用的所有复杂性,这些复杂性让我在 c 中发疯。在 Python 中,一切都按我预期的方式工作,我很快意识到可变/不可变的区别在其中起着重要作用。

当然,仍然存在一些问题(可变函数参数默认值是一个值得注意的例子),但总的来说,我觉得可变/不可变的区别极大地阐明了变量及其值什么以及它们应该如何表现的问题。

但它来自哪里?我不得不假设 GvR 不是第一个想到这种区别的人,Python 也不是第一个使用它的语言。我有兴趣了解使用此概念的早期语言,以及有关它的任何早期理论讨论。

4

4 回答 4

7

如果你喜欢不变性的想法,你应该看看纯函数式语言。在 Haskell中,所有(纯)变量都是不可变的(但仍被称为“变量”,但你去吧)。这是一个好主意——你和编译器都知道将某些东西传递给函数不能以任何方式改变它。

于 2011-07-02T06:41:34.470 回答
5

在 C 中没有明确的不可变概念,因为该语言基于复制语义。在 Python 中,值总是通过引用传递,不变性在保持语言可管理性方面发挥着重要作用。

在 Python 中你没有指针,因为一切都是指针!想象一下,对于一个 Python 程序来说,偶数对象可能会随着时间的推移而改变值意味着什么……你将被迫玩类似这样的把戏

class Shape:
    def __init__(self, points):
        self.points = points[:] # make a copy of the list

不仅适用于列表和字典,还适用于数值和字符串。

因此,基本上在 Python 中,某些类型具有不可变的实例,因为它们通常用作“值”并且您不关心身份。在极少数情况下,您需要例如具有数值的可变对象,您需要将其显式包装在一个类实例中。

在其他基本上基于引用语义的语言中,如 LISP 不变性是程序员的选择,而不是约束,即使许多函数和习惯用法都支持它(很大一部分 LISP 标准库函数是非破坏性的,它确实有点像遗憾的是破坏性的名称并不总是可以清楚地区分)。

因此,例如字符串是可变的 LISP,但实际上可能没有多少 LISP 程序在适当的位置修改字符串,因为这意味着放弃共享的良好可能性,并且需要在许多地方显式复制字符串(在大多数情况下,字符串只是值,而不是对象你关心的身份)。LISP 中的字符串是不可变的吗?不,程序是否会改变它们?几乎从不。

不把选择留给程序员是 Python 语言的精神。当你被迫做出的选择与你的想法一致时,感觉很棒……更少的决定和事情就像你想要的那样。

然而,在我看来,这种方法有两种不同的危险:

  1. 当这些预先做出的选择与您想要或需要做的事情不一致时,就会出现问题。Python 是一门美妙的语言,但如果有不同的独裁者,它可能会变成纯粹的地狱。

  2. 理解和制作 choiches 会迫使您思考并扩展您的思维。不做选择只会在你的脑海中留下一个牢笼,一段时间后你甚至可能没有意识到你正在使用的只是一种可能性,而不是唯一的可能性。一段时间后,你可能会开始认为“事情必须这样”:你甚至不觉得自己是被迫的,因为你的心已经被“肢解”了。

于 2011-07-02T07:22:53.507 回答
4

Objective C 加载了可变/不可变的区别(例如,同时存在NSStringand NSMutableString);它比 Python 早了大约 8 年。Smalltalk,Objective C 继承了它的大部分 OO 设计,在较小程度上使用了这个概念(值得注意的是,字符串不是不可变的;现在的趋势是在 Python、Ruby 等中趋向于不可变字符串)。

于 2011-07-02T03:55:05.930 回答
-2

我建议阅读 Wikipedia 中的以下条目:

于 2011-07-02T06:01:14.200 回答