首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >不可变类型与可变类型

不可变类型与可变类型
EN

Stack Overflow用户
提问于 2011-11-09 03:41:53
回答 7查看 270K关注 0票数 201

我搞不懂什么是不可变类型。我知道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类,但没有标记出任何错误。

EN

回答 7

Stack Overflow用户

发布于 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]
票数 239
EN

Stack Overflow用户

发布于 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]

我已经在内存中创建了123的位置列表。如果我这样做了

e = d

我只是将e指向相同的list d点。然后我可以这样做:

e += [4, 5]

并且ed所指向的列表将被更新以在存储器中也具有45的位置。

如果我返回到不可变类型并使用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))

(这是tuplestuple )作为val,您将收到一个错误,因为tuple没有.clear()方法--您必须将dict(d)作为val传递才能使其工作,在这种情况下,您将得到一个空的SortedKeyDict

票数 39
EN

Stack Overflow用户

发布于 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,现在ac可以“通信”,因为list是可变的,如果你执行c.append('msg'),那么只检查a你就会得到消息。

(顺便说一句,每个对象都有一个与之关联的唯一id号,您可以使用id(x)获取该id号。因此,您可以检查对象是否相同,也可以不检查其唯一id是否已更改。)

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8056130

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档