Python 不可变类型与可变类型

Python 不可变类型与可变类型,python,types,immutability,mutable,Python,Types,Immutability,Mutable,我对什么是不可变类型感到困惑。我知道float对象被认为是不可变的,我的书中有这样的例子: class RoundFloat(float): def __new__(cls, val): return float.__new__(cls, round(val, 2)) 由于类结构/层次结构的原因,这被认为是不可变的吗?这意味着float位于类的顶部,并且是它自己的方法调用。与这类示例类似(尽管我的书中说,dict是可变的): 而可变的东西在类中有方法,例如: class

我对什么是不可变类型感到困惑。我知道
float
对象被认为是不可变的,我的书中有这样的例子:

class RoundFloat(float):
    def __new__(cls, val):
        return float.__new__(cls, round(val, 2))
由于类结构/层次结构的原因,这被认为是不可变的吗?这意味着
float
位于类的顶部,并且是它自己的方法调用。与这类示例类似(尽管我的书中说,
dict
是可变的):

而可变的东西在类中有方法,例如:

class SortedKeyDict_a(dict):
    def example(self):
        return self.keys()

另外,对于最后一个
类(SortedKeyDict_a)
,如果我将此类型的集合传递给它:

d = (('zheng-cai', 67), ('hui-jun', 68),('xin-yi', 2))

不调用
示例
方法,它将返回一个字典。带有
\uuu new\uuu
SortedKeyDict
将其标记为错误。我试着用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>将整数传递给
RoundFloat
类,但它没有标记任何错误。

首先,一个类是否有方法或它的类结构与可变性无关

int
s和
float
s是不可变的。如果我这样做

它将名称
a
指向第一行内存中的某个位置。在第二行,它查找
1
,添加
5
,获取
6
,然后将
a
指向内存中的
6
——它没有以任何方式将
1
更改为
6
。使用其他不可变类型,相同的逻辑适用于以下示例:

对于可变类型,我可以做一些实际更改存储在内存中的值的事情。与:

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

e = d
我只是将
e
指向相同的
列表
d
指向。我可以这样做:

e += [4, 5]
e
d
指向的列表将被更新,以便在内存中也有
4
5
的位置

如果我返回到一个不可变类型,并使用一个
元组

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))

(这是
tuple
中的
tuple
)作为
val
,您会得到一个错误,因为
tuple
s没有
.clear()
方法——您必须将
dict(d)
作为
val
传递,这样您将得到一个空的
SortedKeyDict
,一个类是否有方法或者它的类结构是什么与可变性无关

int
s和
float
s是不可变的。如果我这样做

它将名称
a
指向第一行内存中的某个位置。在第二行,它查找
1
,添加
5
,获取
6
,然后将
a
指向内存中的
6
——它没有以任何方式将
1
更改为
6
。使用其他不可变类型,相同的逻辑适用于以下示例:

对于可变类型,我可以做一些实际更改存储在内存中的值的事情。与:

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

e = d
我只是将
e
指向相同的
列表
d
指向。我可以这样做:

e += [4, 5]
e
d
指向的列表将被更新,以便在内存中也有
4
5
的位置

如果我返回到一个不可变类型,并使用一个
元组

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))

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

对象是否可变取决于其类型。这并不取决于它是否有特定的方法,也不取决于类层次结构的结构

用户定义的类型(即类)通常是可变的。也有一些例外,例如不可变类型的简单子类。其他不可变类型包括一些内置类型,如
int
float
tuple
str
,以及一些用C实现的Python类

一般解释如下:

某些对象的值可以更改。值可以更改的对象 被认为是可变的;对象的值一旦更改就不可更改 创建的对象称为不可变

(不可变容器的值 包含对可变对象的引用的对象可以在 后者的值已更改;但是容器仍然是 被认为是不可变的,因为它包含的对象集合 不可更改。因此,不变性与 一个不可更改的值,它更微妙。)

对象的易变性是 由其类型决定;例如,数字、字符串和元组是 不可变,而字典和列表是可变的


对象是否可变取决于其类型。这并不取决于它是否有特定的方法,也不取决于类层次结构的结构

用户定义的类型(即类)通常是可变的。也有一些例外,例如不可变类型的简单子类。其他不可变类型包括一些内置类型,如
int
float
tuple
str
>>> i = [1,2,3]
>>>id(i)
2146718700
>>> i[0] 
1
>>> i[0] = 7
>>> id(i)
2146718700
x = 5.0
x += 7.0
print x # 12.0
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]
>>> a = [1,2,3]
>>> a.append('hello') # `a` has mutated but is still the same object
>>> a
[1, 2, 3, 'hello']
>>> b = 5.0 
>>> b = b + 0.1
>>> b
5.1
>>> i = 1
>>> id(i)
***704
>>> i += 1
>>> i
2
>>> id(i)
***736 (different from ***704)
>>> a = [1]
>>> id(a)
***416
>>> a.append(2)
>>> a
[1, 2]
>>> id(a)
***416 (same with the above id)
>>> a = 1
>>> a = 2 # I thought int was immutable, but I just changed it?!
my_string = "Hello world" 
my_string[0] = "h"
print my_string 
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
    >>> s='asd'
    >>> s is 'asd'
    True
    >>> s=None
    >>> s is None
    True
    >>> s=123
    >>> s is 123
    True
>>> s={}
>>> s is {}
False
>>> {} is {}
Flase
>>> s=[1,2]
>>> s is [1,2]
False
>>> s=(1,2)
>>> s is (1,2)
False
>>> s=abs
>>> s is abs
True
>>> s=12.3
>>> s is 12.3
False
>>> 12.3 is 12.3
True
>>> s == 12.3
True
>>> id(12.3)
140241478380112
>>> id(s)
140241478380256
>>> s=12.3
>>> id(s)
140241478380112
>>> id(12.3)
140241478380256
>>> id(12.3)
140241478380256
>>>x = 5
>>>y = x
>>>x = x + y
a = [1,2]
b = a
b[1] = 3
a = "Hello"
a +=" World"
print a
"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
a = "Hello World"
a[0] = "M"
TypeError 'str' object does not support item assignment
tuple_a = (1,)
tuple_a[0] = (2,)
print a
'tuple' object does not support item assignment
x=7
y=x
print(x,y)
x=10 # so for immutable objects this creates a new copy so that it doesnot 
#effect the value of y
print(x,y)
x=[1,2,3,4]
print(x)
y=x #for immutable objects assignment doesn't create new copy 
x[2]=5
print(x,y) # both x&y holds the same list
list = [1, 2, 3, 4, 5]
list[0] = '!'
#['!', '2', '3', '4', '5']
y = list
list[0] = 'Hello'
#['Hello', '2', '3', '4', '5']
['Hello', '2', '3', '4', '5']
const a = 10
a = 20
a = 'abcd'
a[0]
#'a'
a[0] = '!'
a += 'e'
#'abcde'
a = a + 'f'