流沙团
Python可变对象和不可变对象 引用,赋值
2022-3-14 流沙团

Python中一切皆对象,每个对象都有其唯一的id,对应的类型和值,其中id指的是对象在内存中的位置。根据对象的值是否可修改分为可变对象和不可变对象。其中,


不可对象包括:数字,字符串,tuple,frozenset(不可变集合)


可变对象包括:list,dict,set


Python中的变量可以指向任意对象,可以将变量都看成是指针,保存了所指向对象的内存地址(对象的引用)。


不可变对象

对于不可变对象,如果要更新变量引用的不可变对象的值,会创建新的对象,改变对象的引用,举个例子


In [41]: x = 1

In [42]: y = x

In [43]: print(id(x))
140719461487648

In [44]: x = 2

In [45]: print(id(y))
140719461487648

In [46]: print(id(x))
140719461487680

In [47]: print(id(2))
140719461487680

上述是int类型的一个实例,可以看到



所以,不可变对象的优点是对于相同的对象,无论多少个引用,在内存中只占用一个地址,缺点是更新需要创建新的对象,因此效率不高。


可变对象

对于可变对象,举个例子


In [57]: a = [1, 2]

In [58]: b = a

In [59]: print(id(a), id(b))
1961088949320 1961088949320

In [60]: a.append(3)

In [61]: print(a, b)
[1, 2, 3] [1, 2, 3]

In [62]: print(id(a), id(b))
1961088949320 1961088949320

In [63]: a = [1, 2, 3]

In [64]: print(id(a))
1961088989704

可以看到



注意,我们研究可变对象的变化,研究的是同一对象,也就是可变指的是append, +=这种操作,而不包括新的赋值操作,赋值操作是会新建一个对象的。比如:


In [96]: a = [1, 2, 3]

In [97]: b = a

In [98]: a = [1]

In [99]: b
Out[99]: [1, 2, 3]

参数传递问题

因为可变对象和不可变对象的特性,因此在参数传递上需要注意


深拷贝和浅拷贝

In [69]: data = [{'name': 'a', 'deleted': True}, {'name' : 'b', 'deleted': False}, {'name': 'c', 'deleted': False}]

In [70]: print(data)
[{'name': 'a', 'deleted': True}, {'name': 'b', 'deleted': False}, {'name': 'c', 'deleted': False}]

In [71]: def add(data_list):
...: for item in data_list:
...: if item.get('deleted'):
...: data_list.remove(item)
...: return data_list
...:

In [72]: add_result = add(data)

In [73]: print(add_result)
[{'name': 'b', 'deleted': False}, {'name': 'c', 'deleted': False}]

In [74]: print(data)
[{'name': 'b', 'deleted': False}, {'name': 'c', 'deleted': False}]

你会发现调用了add方法之后,data已经变了,在之后的代码中你已经无法再使用原来的data了,具体的原因在参数传递那个问题中我有说明。


但是,当你希望在add方法中并不会修改data的值,要怎么做呢?


这时候,你需要了解下深拷贝和浅拷贝


深拷贝和浅拷贝的概念:



所以,上述代码可按需更新为:


def add(data_list):
ret_data_list = deepcopy(data_list)
for item in ret_data_list:
if item.get('deleted'):
ret_data_list.remove(item)
return ret_data_list

变量测试的一个demo

def get_dict(dict1):
# dict1["a3"] = 4
for k,v in dict1.items():
# dict1 = {
# "b1":4,
# "b2":5
# }
dict1 = v
# dict2 = dict1
# dict2["a2"]=4
print(v)

dict1 = {
"a1":2,
"a2":3
}

get_dict(dict1)
print(dict1)
`
发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容