2016-05-31 77 views
8

我了解Python中可变对象和不可变对象的区别。我已经阅读了很多文章,讨论这些差异。但是,我还没有读到任何有关为什么整数是不可变的对象。为什么整数在Python中是不可变的?

是否存在这样的原因?或者答案是“这是怎么回事”?

编辑:我得到提示将这个问题与其他问题区分开来,因为它似乎是以前提出的问题。然而,我相信我所要求的更多是哲学上的Python问题,而不是技术性的Python问题。

似乎Python中的“原始”对象(即字符串,布尔值,数字等)是不可变的。我还注意到,由基元组成的派生数据类型(即字典,列表,类)是可变的。

无论对象是否可变,绘制线的位置是?原始与派生?

+11

你想要改变一个整数究竟是什么?位? –

+0

假设某些类型的不变性可以实现各种优化。这些优化对于'str'来说是_most_发音,但它们也起作用于'int','float','tuple','frozenset' ......有些人可能会认为不变性使得代码更易于阅读情况也一样。再加上事实上,没有一种自然的方式来改变整数(除了'+ =','* =',...这是非常罕见的......),而且似乎并不好没有一成不变的理由。 – mgilson

+0

如果你可以修改值'1'为'2',值'2'为'1',那么'2 + 2 == 1'就是'true';那真的是你想要的吗? –

回答

10

使整数可变将与我们习惯使用它们的方式非常不直观。

考虑以下代码片段:

a = 1  # assign 1 to a 
b = a+2  # assign 3 to b, leave a at 1 

后这些任务执行我们预计一个有值1和b有值3加法运算是创建一个新的整数值从存储的整数和整数2的一个实例。 如果加法操作只取整数a并且只是突变它然后ab将具有值3.

因此,我们期望算术运算为其结果创建新值 - 而不是改变它们的输入参数。

但是,在某些情况下,更改数据结构更方便更高效。假设目前list.append(x)没有修改list,但返回了list的新副本,并且附加了x。 然后这样的功能:

def foo(): 
    nums = [] 
    for x in range(0,10): 
    nums.append(x) 
    return nums 

将只返回空列表。 (记住 - 在这里nums.append(x)不会改变nums - 它返回与x一个新的列表添加数据,但这个新的列表不保存任何地方。)

我们将不得不写foo程序是这样的:

def foo(): 
    nums = [] 
    for x in range(0,10): 
    nums = nums.append(x) 
    return nums 

(这其实是非常相似,在使用Python字符串局面直到大约2.6或者是2.5)。

而且,我们每次分配nums = nums.append(x)时间,我们将复制大小为导致增加的列表在二次行为。 由于这些原因,我们列出了可变对象对象。

的后果,以使列出可变的是,这些语句后:

a = [1,2,3] 
b = a 
a.append(4) 

列表b已更改为[1,2,3,4]。这是我们生活的东西,尽管它现在仍然让我们trips trips不安。

+1

我不认为'使整数可变会使我们习惯于与它们一起工作的方式非常相反。''必然是正确的。还有很多其他语言都有可变的整数('C'是一个很常见的例子......)。仅仅因为我们已经习惯了python整数是不可变的*现在*并不意味着我们在做出最初的决定时习惯了不变的整数。 – mgilson

+1

“a + = 2”创建一个新的整数对我来说是直观的。但大多数时候,它确实没有什么区别。想到的一个关键的帖子是[这一个](https://stackoverflow.com/questions/306313/is-operator-behaves-unexpectedly-with-integers),这是一个更奇怪的事实,“新“整数并不总是创建 –

+0

@mgilson - 你会认为'int'值在C中是可变的吗?当然'gmp' bigint对象是可变的,但我没有看到C'ints'以相同的方式变化。最终,我认为我们会发现使Python整数可变会导致更多的问题,而不是解决问题。我们真正想要做的是让我们的编译器/运行时更加智能,以便他们能够检测到他们何时使用突变而不是创建新对象。这将给我们带来不变价值安全的可变值的效率。 – ErikR

2

什么是使数字在Python中不可变的设计决策?

不变性有几个原因,让我们先看看不变性的原因是什么?

1- 存储器

  • 节省存储器。如果众所周知的是一个对象是不可变的,那么它可以很容易地被复制,从而为同一个对象创建一个新的引用。
  • 表现。 Python可以在创建时为不可变对象分配空间,并且存储需求是固定不变的。

2- 快速执行

  • 它不必复制对象的每个部分,只是一个简单的参考。
  • 易于比较,通过引用比较相等比比较值更快。

3- 安全

  • 在多线程应用程序不同的线程可以与包含在不变的对象内部的数据进行交互,而无需担心数据的一致性。
  • 即使您有例外,程序的内部状态也会保持一致。
  • 类应该是一成不变的,除非有一个很好的理由让他们可变....如果一个类不能进行能不变,限制了它的可变性尽可能

4- 易于使用

  • 易于阅读,易于维护且不太可能以奇怪和不可预知的方式失败。
  • 不变对象更容易测试,这不仅因为它们易于实现的可模仿性,还因为它们倾向于强制执行的代码模式。

5- Keys must be immutable。这意味着你可以使用字符串,数字或元组作为字典键。这是你想使用的东西。

The hash table implementation of dictionaries uses a hash value calculated from the key value to find the key. If the key were a mutable object, its value could change, and thus its hash could also change. But since whoever changes the key object can’t tell that it was being used as a dictionary key, it can’t move the entry around in the dictionary. Then, when you try to look up the same object in the dictionary it won’t be found because its hash value is different. If you tried to look up the old value it wouldn’t be found either, because the value of the object found in that hash bin would be different. 

回过头来看看这个整数:

  • 安全(),使用方便(),并使用数字作为字典键的能力( )是使数字不可变的决定的原因。

  • 自创建时起就有固定内存要求()。

  • Python中的所有对象都是“元素”对象,数字(如字符串)是“元素”对象。没有任何活动会将价值8改变成其他任何东西,并且没有任何活动会将字符串“八”改变为其他任何东西。这是因为decision in the design也是。

相关问题