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'