我对什么是不可变类型感到困惑。我知道float对象被认为是不可变的,我的书中有这样的例子:
class RoundFloat(float):
def __new__(cls, val):
return float.__new__(cls, round(val, 2))
因为类结构/层次结构,这被认为是不可变的吗?,这意味着float位于类的顶部,是它自己的方法调用。类似于这种类型的例子(即使我的书说dict是可变的):
class SortedKeyDict(dict):
def __new__(cls, val):
return dict.__new__(cls, val.clear())
然而,可变的东西在类中有方法,例如:
class SortedKeyDict_a(dict):
def example(self):
return self.keys()
同样,对于最后一个类(SortedKeyDict_a),如果我将这种类型的set传递给它:
d = (('zheng-cai', 67), ('hui-jun', 68),('xin-yi', 2))
不调用示例方法,它将返回一个字典。带有__new__的SortedKeyDict将其标记为错误。我尝试用__new__将整数传递给RoundFloat类,它没有标记错误。
在我看来,你似乎在争论可变/不可变到底意味着什么。下面是一个简单的解释:
首先,我们需要一个解释的基础。
把你编程的任何东西都想象成一个虚拟对象,一个以二进制数字序列的形式保存在计算机内存中的东西。(不过,不要试图把这个想象得太困难。^^)现在在大多数计算机语言中,你不会直接处理这些二进制数,而是更多地使用二进制数的解释。
例如,你不会想到像0x110, 0xaf0278297319或类似的数字,而是你会想到像6这样的数字或像“Hello, world”这样的字符串。然而,这些数字或字符串是计算机内存中二进制数的一种解释。对于变量的任何值都是如此。
简而言之:我们不是用实际值编程,而是用实际二进制值的解释编程。
Now we do have interpretations that must not be changed for the sake of logic and other "neat stuff" while there are interpretations that may well be changed. For example think of the simulation of a city, in other words a program where there are many virtual objects and some of these are houses. Now may these virtual objects (the houses) be changed and can they still be considered to be the same houses? Well of course they can. Thus they are mutable: They can be changed without becoming a "completely" different object.
现在想想整数:它们也是虚拟对象(计算机内存中的二进制数序列)。如果我们改变其中一个,比如把6的值加1,它还是6吗?当然不是。因此任何整数都是不可变的。
所以:如果虚拟对象的任何变化意味着它实际上变成了另一个虚拟对象,那么它就被称为不可变的。
最后的话:
(1)永远不要把你在现实世界中可变和不可变的经验与某种语言的编程混淆在一起:
每种编程语言都有自己的定义,哪些对象可以静音,哪些对象不可以静音。
因此,虽然您现在可能理解了含义上的差异,但仍然需要学习每种编程语言的实际实现. ...的确,一种语言可能有一个目的,即6可能被削弱为7。然后,这将是相当疯狂或有趣的东西,就像平行宇宙的模拟
(2)这个解释当然是不科学的,它是为了帮助你掌握可变和不可变的区别。
一个类是不可变的,如果该类的每个对象在实例化时都有一个固定的值,以后不能更改
换句话说,要么改变变量(名称)的整个值,要么就不管它。
例子:
my_string = "Hello world"
my_string[0] = "h"
print my_string
你希望这可以工作并打印hello world,但这将抛出以下错误:
Traceback (most recent call last):
File "test.py", line 4, in <module>
my_string[0] = "h"
TypeError: 'str' object does not support item assignment
解释器说:我不能改变这个字符串的第一个字符
你将不得不改变整个字符串,以使其工作:
my_string = "Hello World"
my_string = "hello world"
print my_string #hello world
查看这个表格:
源
可变和不可变对象之间的区别
定义
可变对象:创建后可以更改的对象。
不可变对象:创建后不能更改的对象。
在Python中,如果你改变了不可变对象的值,它会创建一个新对象。
可变的对象
下面是Python中可变类型的对象:
列表
字典
集
中bytearray
用户定义的类
不可变对象
以下是Python中不可变类型的对象:
int
浮动
小数
复杂的
保龄球
字符串
元组
范围
frozenset
字节
一些悬而未决的问题
问:字符串是不可变类型吗?
回答:是的,但你能解释一下吗?
证据1:
a = "Hello"
a +=" World"
print a
输出
"Hello World"
在上面的例子中,字符串被创建为“Hello”,然后更改为“Hello World”。这意味着字符串是可变类型的。但当我们检查它的标识,看它是否为可变类型时,就不是这样了。
a = "Hello"
identity_a = id(a)
a += " World"
new_identity_a = id(a)
if identity_a != new_identity_a:
print "String is Immutable"
输出
String is Immutable
证据2:
a = "Hello World"
a[0] = "M"
输出
TypeError 'str' object does not support item assignment
问:元组是不可变类型吗?
答案:是的。
证据1:
tuple_a = (1,)
tuple_a[0] = (2,)
print a
输出
'tuple' object does not support item assignment