python 赋值和引用
1、Python中一切皆为对象
不管是集合变量还是数值型或者字符串型的变量都是一个引用,都是指向对应内存空间中的对象。 一个对象都有两个标准的头部信息:一个类型标识符去标识这个对象的类型,以及一个引用的计数器,用来决定是不是可以回收这个对象。当没有对象指向这块内存区域,python会自动进行回收。
2、赋值操作总是储存对象的引用,而不是这些对象的拷贝。··
python中的变量在赋值的时候创建,它可以引用所有类型的对象,变量就相当于一个指针,指向对象所占的内存空间
>>> a = 1
>>> b = a
>>> print("a的ID:",id(a))
a的ID: 1408529040
>>> print("b的ID:",id(b))
b的ID: 1408529040
>>> a = 3
>>> print('a=%d ,b=%d ' % (a,b))
a=3 ,b=1
>>> print("a的ID:",id(a))
a的ID: 1408529104
>>> print("b的ID:",id(b))
b的ID: 1408529040
这里a赋值给b之后,a和b的地址是相同的,他们指向同一个对象的内存空间,当改变对a赋值常量,这时候开辟了新的内存空间存放3,这是a指向了新的内存空间,a和b的地址不在相同
>>> list1 = [1,2,3]
>>> list2 = list1
>>> print("list1的ID:",id(list1))
list1的ID: 1230502136904
>>> print("list2的ID:",id(list2))
list2的ID: 1230502136904
>>> list1[0] = 0
>>> print('list1=%s ,list2=%s ' % (list1,list2))
list1=[0, 2, 3] ,list2=[0, 2, 3]
上面list1和list2指向同一内存空间,改变其中一个列表中的元素,另一个也会改变。
深拷贝和浅拷贝
深拷贝和浅拷贝的区别在python里,主要是list列表中的元素如果还是个列表,这就需要使用深拷贝,因为只是浅拷贝的话,列表中的列表在list1和list2中是同一块内存。
>>> list1 = [1,2,3]
>>> list1 = [1,2,3,[4,5,6],7]
>>> list2 = list1[:]
>>> print("list1的ID:",id(list1))
list1的ID: 1230502136712
>>> print("list2的ID:",id(list2))
list2的ID: 1230502136776
>>> print("list1[3]的ID:",id(list1[3]))
list1[3]的ID: 1230502135944
>>> print("list2[3]的ID:",id(list2[3]))
list2[3]的ID: 1230502135944
列表中的切片是浅拷贝,这里会看到list1和list2指向不同内存空间,但是他们的第三个元素也就是列表中的列表,是同一个内存空间的数据,也就是说浅拷贝不能拷贝列表中的列表。当然元祖也是相同的,但是元组是不能修改的,安全一些。
所以这里要使用深拷贝 import copy 中的copy.deepcopy()
>>> list1 = [1,2,3,[4,5,6],7]
>>> list2 = list1[:] #浅拷贝
>>> list3 = copy.deepcopy(list1) #深拷贝
>>> print("list1[3]的ID:",id(list1[3]))
list1[3]的ID: 1230502136904
>>> print("list2[3]的ID:",id(list2[3]))
list2[3]的ID: 1230502136904 #浅拷贝的列表中的列表地址和list1相同
>>> print("list3[3]的ID:",id(list3[3]))
list3[3]的ID: 1230502136456 #深拷贝的列表中的列表地址和list1就不相同了
更详细的的深拷贝和浅拷贝的内容(https://www.cnblogs.com/zipxzf/articles/9737680.html)
这里注意:列表和数组不同,numpy ndaray数组中切片和np.view()相同,创建一个数组的视图,不是拷贝。
python 字典
1、{key:value} 健:值
一个对象能不能作为字典的key,就取决于其有没有__hash__方法。所以所有python自带类型中,除了list、dict、set和内部至少带有上述三种类型之一的tuple之外,其余的对象都能当key。
字典是映射类型,列表元祖字符串是序列类型
dict1 = {} 创建字典
dict() 函数创建字典
>>> dict1 = dict((('a',1),('b',2),('c',3),('d',4)))
>>> dict1
{'c': 3, 'b': 2, 'd': 4, 'a': 1}
字典是无序的,所以dict[1]会报错
键值不存在,赋值会创建键值对
>>> dict1['e'] = 5
>>> dict1
{'c': 3, 'b': 2, 'd': 4, 'a': 1, 'e': 5}
2、内建函数
1> fromkeys() 返回字典
>>> dict1={}
>>> dict1.fromkeys((1,2,3))
{1: None, 2: None, 3: None}
>>> dict1.fromkeys((1,2,3),'Number')
{1: 'Number', 2: 'Number', 3: 'Number'}
>>> dict1.fromkeys((1,2,3),('one','two','three'))
{1: ('one', 'two', 'three'), 2: ('one', 'two', 'three'), 3: ('one', 'two', 'three')}
>>> dict1.fromkeys((1,3),'数字')
{1: '数字', 3: '数字'}
2> 访问字典 keys(),values(),items() 循环好搭档
keys() 返回键
>>> for eachKey in dict1.keys():
... print(eachKey)
values() 返回值
>>> for eachValue in dict1.values():
... print(eachValue)
items() 返回键值对
>>> for eachItem in dict1.items():
... print(eachItem)
3> get()
字典访问键不存在会报错,使用get()访问不存在的健返回None,或者指定一个返回值
>>> dict1
{'c': 3, 'b': 2, 'd': 4, 'a': 1, 'e': 5}
>>> dict1.get('a')
1
>>> print(dict1['f']) #报错
Traceback (most recent call last):
File "<pyshell#96>", line 1, in <module>
print(dict1['f'])
KeyError: 'f'
>>> print(dict1.get('f')) #返回None
None
>>> dict1.get('f','不存在') #指定 get()返回值
'不存在'
4> in
in查找健是否在字典中
>>> 'a' in dict1
True
>>> 'g' in dict1
False
5> clear() 清空字典
字典b赋值给字典a之后,clear()操作其中一个可以清空两个字典
>>> dict1.clear()
>>> dict1
{}
赋值是引用所以清空dict1,dict2也会被清空
>>> dict1 = {'a':1, 'b':2}
>>> dict1 = dict2
>>> dict1.clear()
>>> dict1
{}
>>> dict2
{}
6> copy() 浅拷贝
浅拷贝和赋值是不同的
>>> a.clear()
>>> a= {1:'one',2:'two',3:'three'}
>>> b=a.copy()
>>> c=a
>>> c
{1: 'one', 2: 'two', 3: 'three'}
>>> a
{1: 'one', 2: 'two', 3: 'three'}
>>> b
{1: 'one', 2: 'two', 3: 'three'}
>>> id(a)
1634644066520
>>> id(b)
1634644247824
>>> id(c)
1634644066520
>>> c[4]='four'
>>> c
{1: 'one', 2: 'two', 3: 'three', 4: 'four'}
>>> a
{1: 'one', 2: 'two', 3: 'three', 4: 'four'}
>>> b
{1: 'one', 2: 'two', 3: 'three'}
赋值的c和a地址相同,改变a,c也会改变而b不会被改变,
无条件值的分片以及字典copy方法只能做浅层复制,不能够复制嵌套的数据结构,如果需要一个深层嵌套的数据结构的完整的、完全独立的拷贝,那么就要使用标准的copy模块,即浅拷贝和深拷贝。
7> pop() 和 popitem 弹出 可以从字典里删除
pop(key)需要键值做参数,popitem()不要参数,弹出首个
>>> dict1
{'b': 2, 'd': 4, 'a': 1}
>>> dict1.pop('a')
1
>>> dict1.popitem()
('b', 2)
8> setdefault
添加字典键值对,键不存在,值为None
>>> a.setdefault('呵')
>>> a
{1: 'one', 2: 'two', 3: 'three', 4: 'four', '呵': None}
>>> a.setdefault(5,'five')
'five'
>>> a
{1: 'one', 2: 'two', 3: 'three', 4: 'four', '呵': None, 5: 'five'}
构造值为列表的字典
>>> d={}
>>> d.setdefault('a',[]).append(1)
>>> d.setdefault('a',[]).append(2)
>>> d.setdefault('b',[]).append(4)
>>> d
{'a': [1, 2], 'b': [4]}
也可以使用defaultdict
>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> d['a'].append(1)
>>> d['a'].append(2)
>>> d['b'].append(4)
>>> d
defaultdict(<class 'list'>, {'a': [1, 2], 'b': [4]})
default会自动为将要访问的键创建映射实体,setdefault不会
9> update() 更改值
>>> a
{1: 'one', 2: 'two', 3: 'three', 4: 'four', '呵': None, 5: 'five'}
>>> b={'呵':'呵呵'}
>>> a.update(b)
>>> a
{1: 'one', 2: 'two', 3: 'three', 4: 'four', '呵': '呵呵', 5: 'five'}
python 集合 set
1、set 也是用{}表示,没有映射关系
>>> num={}
>>> type(num)
<class 'dict'>
>>> num2={1,2,3,4,5}
>>> type(num2)
<class 'set'>
set中元素不能重复,set会删除重复的元素只保留一份,并且集合是无序的所以不支持索引
>>> num2={1,2,3,4,5,5,4,3,2}
>>> num2
{1, 2, 3, 4, 5}
>>> num2[2]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'set' object does not support indexing
2、set 创建
num = {1, 2, 3, 4, 5}
或用set()函数 参数可以使元组或者列表
>>> set1 =set([1,2,3,4,5,5])
>>> set1
{1, 2, 3, 4, 5}
3、in 和not in 判断元素是否在集合中
>>> num
{8, 9, 3, 5, 6}
>>> 8 in num
True
>>> 8 not in num
False
>>> 0 in num
False
4、add(num) 添加元素 和 remove(num) 删除元素
>>> num.add(10)
>>> num
{3, 5, 6, 8, 9, 10}
>>> num.remove(8)
>>> num
{3, 5, 6, 9, 10}
4、不可变集合 frozenset()
不能改变集合
>>> num = frozenset([1,2,3,4,5])
>>> num
frozenset({1, 2, 3, 4, 5})
>>> num.add(8)
Traceback (most recent call last):
File "<pyshell#148>", line 1, in <module>
num.add(8)
AttributeError: 'frozenset' object has no attribute 'add
集合(s).方法名
|
等价符号
|
方法说明
|
s.issubset(t) | s <= t | 子集测试(允许不严格意义上的子集):s 中所有的元素都是 t 的成员 |
s < t | 子集测试(严格意义上):s != t 而且 s 中所有的元素都是 t 的成员 | |
s.issuperset(t) | s >= t | 超集测试(允许不严格意义上的超集):t 中所有的元素都是 s 的成员 |
s > t | 超集测试(严格意义上):s != t 而且 t 中所有的元素都是 s 的成员 | |
s.union(t) | s | t | 合并操作:s "或" t 中的元素 |
s.intersection(t) | s & t | 交集操作:s "与" t 中的元素 |
s.difference | s - t | 差分操作:在 s 中存在,在 t 中不存在的元素 |
s.symmetric_difference(t) | s ^ t | 对称差分操作:s "或" t 中的元素,但不是 s 和 t 共有的元素 |
s.copy() | 返回 s 的拷贝(浅复制) | |
以下方法仅适用于可变集合
| ||
s.update | s |= t | 将 t 中的元素添加到 s 中 |
s.intersection_update(t) | s &= t | 交集修改操作:s 中仅包括 s 和 t 中共有的成员 |
s.difference_update(t) | s -= t | 差修改操作:s 中包括仅属于 s 但不属于 t 的成员 |
s.symmetric_difference_update(t) | s ^= t | 对称差分修改操作:s 中包括仅属于 s 或仅属于 t 的成员 |
s.add(obj) | 加操作:将 obj 添加到 s | |
s.remove(obj) | 删除操作:将 obj 从 s 中删除,如果 s 中不存在 obj,将引发异常 | |
s.discard(obj) | 丢弃操作:将 obj 从 s 中删除,如果 s 中不存在 obj,也没事儿^_^ | |
s.pop() | 弹出操作:移除并返回 s 中的任意一个元素 | |
s.clear() | 清除操作:清除 s 中的所有元素 |