我搞不懂什么是不可变类型。我知道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()
另外,对于最后一个class(SortedKeyDict_a)
,如果我将此类型的set传递给它:
d = (('zheng-cai', 67), ('hui-jun', 68),('xin-yi', 2))
在不调用example
方法的情况下,它返回一个字典。带有__new__
的SortedKeyDict
将其标记为错误。我尝试使用__new__
将整数传递给RoundFloat
类,但没有标记出任何错误。
发布于 2011-11-09 09:50:59
什么?浮点数是不变的吗?但是我不能做吗
x = 5.0
x += 7.0
print x # 12.0
那不是"mut“x吗?
你也同意字符串是不变的,对吧?但你也可以做同样的事情。
s = 'foo'
s += 'bar'
print s # foobar
变量的值会更改,但它会通过更改变量引用的内容来更改。可变类型可以以这种方式更改,也可以“就地”更改。
这是不同之处。
x = something # immutable type
print x
func(x)
print x # prints the same thing
x = something # mutable type
print x
func(x)
print x # might print something different
x = something # immutable type
y = x
print x
# some statement that operates on y
print x # prints the same thing
x = something # mutable type
y = x
print x
# some statement that operates on y
print x # might print something different
具体的例子
x = 'foo'
y = x
print x # foo
y += 'bar'
print x # foo
x = [1, 2, 3]
y = x
print x # [1, 2, 3]
y += [3, 2, 1]
print x # [1, 2, 3, 3, 2, 1]
def func(val):
val += 'bar'
x = 'foo'
print x # foo
func(x)
print x # foo
def func(val):
val += [3, 2, 1]
x = [1, 2, 3]
print x # [1, 2, 3]
func(x)
print x # [1, 2, 3, 3, 2, 1]
发布于 2011-11-09 03:48:20
首先,一个类是否有方法或者它的类结构是什么与可变性无关。
int
%s和float
%s是不可变的。如果我这样做了
a = 1
a += 5
它将名称a
指向内存中第一行上的某个1
。在第二行,它查找1
,添加5
,获取6
,然后将a
指向内存中的6
--它没有以任何方式将1
更改为6
。同样的逻辑也适用于以下使用其他不可变类型的示例:
b = 'some string'
b += 'some other string'
c = ('some', 'tuple')
c += ('some', 'other', 'tuple')
对于可变类型,我可以实际改变值在内存中的存储位置。通过以下方式:
d = [1, 2, 3]
我已经在内存中创建了1
、2
和3
的位置列表。如果我这样做了
e = d
我只是将e
指向相同的list
d
点。然后我可以这样做:
e += [4, 5]
并且e
和d
所指向的列表将被更新以在存储器中也具有4
和5
的位置。
如果我返回到不可变类型并使用tuple
f = (1, 2, 3)
g = f
g += (4, 5)
那么f
仍然只指向原来的tuple
--您已经将g
指向了一个全新的tuple
。
现在,以您的示例
class SortedKeyDict(dict):
def __new__(cls, val):
return dict.__new__(cls, val.clear())
你路过的地方
d = (('zheng-cai', 67), ('hui-jun', 68),('xin-yi', 2))
(这是tuples
的tuple
)作为val
,您将收到一个错误,因为tuple
没有.clear()
方法--您必须将dict(d)
作为val
传递才能使其工作,在这种情况下,您将得到一个空的SortedKeyDict
。
发布于 2013-01-22 12:02:04
可变对象必须至少有一个能够改变该对象的方法。例如,list
对象具有append
方法,该方法实际上会使对象发生变化:
>>> a = [1,2,3]
>>> a.append('hello') # `a` has mutated but is still the same object
>>> a
[1, 2, 3, 'hello']
但是float
类没有方法来改变float对象。您可以执行以下操作:
>>> b = 5.0
>>> b = b + 0.1
>>> b
5.1
但是=
操作数不是一个方法。它只是在变量和它右边的任何东西之间做了一个绑定,没有其他东西。它从不更改或创建对象。从现在开始,它是变量将指向的声明。
执行b = b + 0.1
时,=
操作数将变量绑定到一个新的浮点数,该浮点数是使用5 + 0.1
的结果创建的。
将变量赋给现有对象时,=
操作数会将该变量绑定到该对象。没有更多的事情发生
在任何一种情况下,=
都会进行绑定。它不会更改或创建对象。
执行a = 1.0
时,=
操作数不是创建浮点数的操作数,而是行的1.0
部分。实际上,当您编写1.0
时,它是float(1.0)
的简写,构造函数调用返回一个float对象。(这就是为什么如果您键入1.0
并按enter键,您会得到下面打印的"echo“1.0
的原因;这是您调用的构造函数的返回值)
现在,如果b
是一个浮点型,你赋值为a = b
,两个变量都指向同一个对象,但实际上变量之间不能相互通信,因为这个对象是不可变的,如果你这样做,现在b
指向一个新对象,而a
仍然指向oldone,不知道b
指向的是什么。
但是如果c
是一个list
,假设你分配了a = c
,现在a
和c
可以“通信”,因为list
是可变的,如果你执行c.append('msg')
,那么只检查a
你就会得到消息。
(顺便说一句,每个对象都有一个与之关联的唯一id号,您可以使用id(x)
获取该id号。因此,您可以检查对象是否相同,也可以不检查其唯一id是否已更改。)
https://stackoverflow.com/questions/8056130
复制相似问题