【问题标题】:Purposes of introducing immutable objects in Python?在 Python 中引入不可变对象的目的是什么?
【发布时间】:2017-07-13 18:20:04
【问题描述】:
  1. 在 Python 中引入不可变对象的目的是什么?

    • 它是否与使用参考模型的 Python 有关(即变量是指向对象而不是容器的指针? 对象的值)?

      我猜不是,因为 Python 对所有类型都使用参考模型, 并非所有类型都需要不可变对象。

    • Python 中的不变性是否被用作函数范式的一部分?如果是,怎么做?

      例如,我们不能通过分配给它的一个来更改字符串 职位。

      >>> S
      'Spam'
      >>> S[0] = 'z'             # Immutable objects cannot be changed
      ...error text omitted...
      TypeError: 'str' object does not support item assignment
      

      但我们总是可以构建一个新的并将其分配给相同的名称。 这是否背叛了功能不变性的目的 范式,并与命令式范式保持一致?但是在命令式范式中,根据不变性和参考模型来实现可变性是低效的。

      >>> S = 'z' + S[1:]        # But we can run expressions to make new objects
      >>> S
      'zpam'
      
  2. 某些类型被设计为使用不可变对象(数字、字符串、元组)而其他类型(列表、字典、集合)使用可变对象而不是所有类型不可变或可变的原因是什么?

    是否有一些规则可以判断一个类型是否需要不变性或可变性? 原始对象(即相对于复合对象)是否必须是不可变的?

谢谢。

【问题讨论】:

  • Python 没有 原始类型。
  • 不变性通常会减少错误代码,但是,可变和不可变对象各有利弊。一般来说,严格的功能范式不允许重新分配变量。虽然你可以不遗余力地编写 Python 的纯函数子集,但它基本上是一种命令式语言,其中包含一些函数构造。
  • 不变性很有用。可变性很有用。我们都有。涵盖使用其中一种或另一种的所有原因,或者为什么某些类型是可变或不可变的,对于 Stack Overflow 问题来说过于宽泛,而且它实际上并不是一个 Python 问题。
  • 不是完全重复,但解释了为什么整数是不可变的:stackoverflow.com/questions/37535694/…。简而言之,拥有不可变数据类型允许您将对象视为只是一个值。但正如@user2357112 一样,还有其他原因,列出所有这些对于 Stack Overflow 来说过于广泛。

标签: python language-design


【解决方案1】:

在 Python 中引入不可变对象的目的是什么?

任何语言中引入不可变对象有什么意义?

...我们不能通过分配一个位置来改变一个字符串...但是我们总是可以建立一个新的并将它分配给相同的名称。这是否背叛了函数式范式中不变性的目的,并与命令式范式保持一致?但是在命令式范式中,根据不可变性和参考模型来实现可变性是低效的。

实际上,这在实现中并不少见 - C# 字符串以完全相同的方式实现(对不可变对象的可变引用)。

一些将字符数组用于字符串的语言(如C)具有事实上不可变字符串长度(但每个字符都是可变的)。

请记住,“不变性”有许多相互竞争的定义。 (不久前我读了一篇论文,列出并解释了所有这些,但我现在找不到它)。例如,它是否意味着对可变对象的常量引用(浅不变性)?还是对不可变对象的常量引用(深度不变性)?甚至是对不可变对象的“非固定”引用?这实际上取决于您想要使不变性有多“深”,以及如何在不“破坏”向后兼容性的情况下实现它。 (关于向后兼容性问题,请注意 C++、C#、Java、F# 和许多其他语言实际上必须为常量变量引入特殊关键字 - 例如 Java 中的 final、F# 中的 let、C# 中的 readonly) .

另外一点:许多语言(C#、Python)都具有函数式特性,但不一定是纯粹(甚至主要)函数式语言。很多时候(例如在 C# 中),功能特性在技术上是该语言的新添加,因此为了保持向后兼容性,某些功能特性可能不会像您希望的那样以“纯”功能样式实现。

此外,允许多种范式的部分后果是,您通常可以以并非总是完全健康的方式“混合”它们 - 从句法角度“禁止”范式混合通常是困难或不可能的查看。

为什么某些类型被设计为使用不可变对象(数字、字符串、元组),而其他类型(列表、字典、集合)使用可变对象,而不是所有类型不可变或可变?

因为 Python 是一种多范式语言。不可变数据类型适用于函数式编程,但通常您希望可变数据类型用于面向对象编程。因此,语言必须具有适用于两种范式的特征。正如official documentation on Python's functional features 所说,

某些计算机语言的设计者选择强调一种特定的编程方法。这通常使编写使用不同方法的程序变得困难。其他语言是支持多种不同方法的多范式语言。 Lisp、C++ 和 Python 是多范式;您可以使用所有这些语言编写大部分程序化、面向对象或函数式的程序或库。在大型程序中,不同的部分可能使用不同的方法编写;例如,GUI 可能是面向对象的,而处理逻辑是程序性的或功能性的。

所以,基本上,Python 希望允许您选择您的范例(甚至能够在同一个程序中混合使用它们)。这实际上非常方便 - 许多框架(例如 .NET)现在都在鼓励它。 (例如,WPF/XAML 倾向于鼓励 GUI 的声明范式)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-31
    • 1970-01-01
    • 2011-06-02
    • 2012-09-18
    • 1970-01-01
    • 2010-12-29
    相关资源
    最近更新 更多