今日内容:列表补充 元组类型 字典类型
列表之深浅copy
深浅copy介绍
拷贝就是copy,也就是复制的意思。
深浅拷贝顾名思义就存在深拷贝和浅拷贝两种情况。
b = ['zz', 'yy']
a = [1, 2, 3, 4, b]
浅拷贝:
a.copy()
或者a[:]
这样a列表就完成了一次浅拷贝
例如:
list = [1,2,3,4]
new_list = list.copy() # ===> 这时会浅copy list 列表 返回一个新的列表new_list
new_list1 = list[:]
深拷贝:
import copy
list = [1,2,3,4]
new_list = copy.deepcopy(list) # ===> 这时会深copy list 列表 返回一个新的列表new_list
这样list列表就完成了一次深拷贝。
浅拷贝list.copy()等价于copy.copy(list)
深拷贝和浅拷贝的区别
浅拷贝只拷贝第一层的即l列表的存储数据地址,如果此时b列表(子列表)发生了修改,则new_l列表中b列表的数据也会发生变化,此时数据复制的结果就会不准确.
浅copy的原理图
案例:
l = [11, 22, ['xx', 'yy']]
new_l = l.copy() # t等同于new_l = l[:]
new_l[0] = 00 # 改变的列表对应的元素为11,是一个整型为一个不可变类型的数据,它改变的仅仅是自己,不会影响到原来(关联)的列表
print(l) # ====> [11, 22, ['xx', 'yy']]
print(new_l) # ====>[0, 22, ['xx', 'yy']]
new_l[2][1] = 'zzz' # 此时改变的是列表中的子列表元素['xx', 'yy'] ,子列表是一个列表类型的数据,为一个可变类型,它不仅会改变自己,也会改变原来(关联)的列表
print(l) # ====> [11, 22, ['xx', 'zzz']]
print(new_l) # =====> [11, 22, ['xx', 'zzz']]
print(id(l[0]), id(l[1]), id(l[2])) # ===> 140718605693504 140718605693856 1699776254536
print(id(new_l[0]), id(new_l[1]), id(new_l[2])) # ===> 140718605693504 140718605693856 1699776254536
总结:浅copy一个列表后,如果copy的列表中的元素有可变类型的数据,当改变其中一个列表中的可变类型对应的值,时俩个值都会受影响.而元素的数据类型为不可变的,则不会影响.
因为声明一个列表的变量时.变量名对应的值是一个索引和索引相对应的元素的值的内存地址,再通过内存地址绑定到索引指向的值,所以当索引指向的值的数据类型为可变的数据类型时,它绑定的值又会延续到下一个索引对应的索引的值的内存地址.也就是说浅copy的元素为可变类型时,它们的子列表的索引对应的内存地址的计数是1,公用一条,
当发生改变时,计数变为0,重新指向同一个内存地址.
为了杜绝这种情况,我们需要进行深拷贝,把进行嵌套的所有列表数据都复制一遍,这样不管哪一层数据发生变化,对我们已经复制的数据都不会产生影响。
深copy底层原理图:
深copy会将子列表申请一个新的内存空间,值是一样的.避免改一个而牵连俩个列表.
案例:
from copy import deepcopy
l = [11, 22, ['xx', 'yy']]
new_l1 = deepcopy(l) # 深copy
print(id(l[0]), id(l[1]), id(l[2])) # # ===> 140718605693504 140718605693856 1699776254536
print(id(new_l1[0]), id(new_l1[1]), id(new_l1[2])) # ====> 140718605693504 140718605693856 1699780262472
列表内置方法的补充
需要掌握的
代码中===>后接的是返回结果
l_list = [11, 22, 33, 44, 55, 66, 22, 22, 33]
print(l_list.index(11)) # 列表中的元素对应的索引,返回值是一个索引 ==> 0
print(len(l_list)) # 列表元素的个数 l.__len__()返回值是一个数字 ==> 9
print(l_list.count(33)) # 列表中元素出现的个数 返回值是一个数字 ==> 2
print(l_list.clear()) # 清空一个列表 返回值为None ===> None
print(l_list) # ===> []
l_list1 = [11, 22, 33, 99, 88, 44, 55, 66, 77]
print(l_list1.extend([77, 88])) # 往列表中添加多个值(值为一个可迭代对象) 返回的是None
print(l_list1) # ===> [11, 22, 33, 99, 88, 44, 55, 66, 77, 77, 88]
print(l_list1.reverse()) # 将列表中的元素,反着存放 返回的是None
print(l_list1) # ===> [88, 77, 77, 66, 55, 44, 88, 99, 33, 22, 11]
print(l_list1.sort()) # 将列表中的元素排序,默认是升序 返回的是None
print(l_list1) # ===> [11, 22, 33, 44, 55, 66, 77, 77, 88, 88, 99]
print(l_list1.sort(reverse=True)) # 降序 将 reverse=True, 返回的是None
print(l_list1) # ====> [99, 88, 88, 77, 77, 66, 55, 44, 33, 22, 11]
列表函数(了解)
序号 | 函数 |
---|---|
1 | cmp(list1, list2)比较两个列表的元素 |
2 | len(list) 列表元素个数 |
3 | max(list) 返回列表元素最大值 |
4 | min(list)返回列表元素最小值 |
5 | list(seq)将元组转换为列表 |
元组类型
概念:
- 元组与列表类似,不同之处在于元组的元素不能修改。
- 元组使用小括号,列表使用方括号。
- 元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可。
用途: 元组就相当于一种不可变的列表,所以说元组包含的元素可以是任意类型
作用:存多个值,对比列表来说,元组不可变(是可以当做字典的key的),主要是用来读
定义:与列表类型相似,只不过[]换成()
age=(11,22,33,44,55) # 本质age=tuple((11,22,33,44,55))
需要注意的是在python中()也可以表示包含的意思,所以,当你使用 i = (1),此时的类型还是整型1
要想存一个1为元组的类型:需要在数字1后面的加上一个","
i1 = (1)
print(i1, type(i1)) # ===> 1 <class 'int'>
i2 = (1,)
print(i2, type(i2)) # ====> (1,) <class 'tuple'>
优先掌握的操作:
提示:详细用法请看前面的列表类型
# 1、按索引取值(正向取+反向取):只能取
t_tuple = (11, 22, 33, 44, 55)
print(t_tuple[0], t_tuple[-1]) # ===> 11 55
# #2、切片(顾头不顾尾,步长)
print(t_tuple[0:2]) # ==> (11, 22)
# #3、长度
print(len(t_tuple)) # ===> 5
# #4、成员运算in和not in
print(11 in t_tuple) # ===> True
#5、循环
for t in t_tuple:
print(t)
修改元组
元组中的元素值是不允许修改的,但我们可以对元组进行连接组合,如下实例
tup1 = (12, 34.56)
tup2 = ('abc', 'xyz')
# tup1[0] = 100 # 这样直接修改元组元素操作是非法的。==> TypeError: 'tuple' object does not support item assignment
# 创建一个新的元组
tup3 = tup1 + tup2
print(tup3) # ===> (12, 34.56, 'abc', 'xyz')
删除元组
元组中的元素值是不允许删除的,但我们可以使用del语句来删除整个元组,如下实例:
del tup1 # 手动释放掉了tup1变量名指向的内存地址,计数为0
print(tup1) # 再引用会报错 ===>NameError: name 'tup1' is not defined
无关闭分隔符
任意无符号的对象,以逗号隔开,默认为元组,如下实例:
print('abc', 11, 22, 'xyz') # ===> abc 11 22 xyz
res = 'abc', 11, 11, 'xyz'
print(type(res)) # ===> <class 'tuple'>
x, y = 1, 2
print("Value of x , y : ", x, y) # ====> Value of x , y : 1 2
字典的数据类型
字典的介绍:
字典是另一种可变容器模型,且可存储任意类型对象。
用途:按照key:value
的方式存放多个值,其中key对value应该有描述性效果
字典的每个键值 key=>value
对用冒号 :
分割,每个键值对之间用逗号 ,
分割,整个字典包括在花括号 {}
中 ,格式如下所示:
d = {key1 : value1, key2 : value2 }
键一般是唯一的,如果重复最后的一个键值对会替换前面的,值不需要唯一。
dict = {'a': 1, 'b': 2, 'b': '3'}
print(dict['b']) # ===> 3
print(dict) # ===> {'a': 1, 'b': '3'}
值可以取任何数据类型,但键必须是不可变的,如字符串,数字或元组。
小知识点:hash与可变不可变是相反的,即kehash的是不可变数据类型,不可hash的为可变数据类型
数据类型转换
调用字典的dict()方法转成字典的类型有局限性.必须为可迭代对象类型且遍历后有俩个值的
例如:
res = dict([('key', 'value'), ['key1', 'value1']]) # ===> {'key': 'value', 'key1': 'value1'}
print(res)
字典的俩种声明方式
d = {} # 推荐
print(d, type(d)) # ===> {} <class 'dict'>
d1 = dict() # 等同于上方的 d = {}
print(d1, type(d1)) # ===> {} <class 'dict'>
如何将变量名绑定一个字典类型的值
语法: dict_obj = {'key1':'value1', 'key2': 'value2'}
案例: 将同学的消息存放在字典中
student_dict = {'name': 'jkey', 'age': 18,'habbies': ['play','eat']}
存了值.我们如何取值
字典中取值的俩种方式:
因为字典是无序的,所以我们不能通过索引取值
按照在dict_obj[key]
取对应的value
按照dict_obj.get(key)
取对应的value
区别:取一个不存在字典中的key时,按照[key]
的方式会报语法错误,而.get(key)
的方式会返回一个None
案例: 在同学消息字典中取出他的名字
student_dict = {'name': 'jkey', 'age': 18,'habbies': ['play','eat']}
print(student_dict[0]) # ==> KeyError: 0
print(student_dict['name']) # jkey
print(student_dict.get('name')) # jkey
当key不存在时
student_dict = {'name': 'jkey', 'age': 18,'habbies': ['play','eat']}
# print(student_dict['XXX']) # 输出 ===> KeyError: 'XXX'
print(student_dict.get('XXX')) # 输出 ====> None
因为字典是一个可变类型,所以它的值可以改变
改字典的值.
通过dict_obj['key']
对相应的value的值进行更改,并且改变原字典
注意:dict_obj.get('key')
只能取值,不能该值.
student_dict = {'name': 'jkey', 'age': 18,'habbies': ['play','eat']}
student_dict['name'] = 'liu'
print(student_dict) # 输出 {'name': 'liu', 'age': 18, 'habbyies': ['play', 'eat']}
# student_dict.get('age') = 11 # 该值会报语法错误=== > SyntaxError: can't assign to function call
居然可以改值,是不是也支持添加值呢???
是的.字典可以添加值
字典添加值的操作
因为字典是无序的,并且是以键值对的方式存放,所以我们可以直接通过dict_obj['new_key']=new_value
是不是和改值一样,只不过此时的key是一个原字典不存在的key,"key"最好是唯一的且字符串的类型
案例:往学生字典中添加一个性别的数值
student_dict = {'name': 'jkey', 'age': 18,'habbies': ['play','eat']}
student_dict['sex'] = 'male'
print(student_dict) # 输出 ===> {'name': 'jkey', 'age': 18, 'habbyies': ['play', 'eat'], 'sex': 'male'}
根据输出结果你可以发现,它是将新的键值对放到字典的最后,这里要提的小知识点是,不管在python2中还是在python3中,字典都是无序的,但是python3中优化了字典的输出.让其看起来像是一个有序的.
那你都可以改了是不是也可以删呢?
是的字典支持删值
方式1:万能删除del
- 功能:将字典中的变量名和内存地址之间的链接清除,可以是清除一个key:value,也可以是一个字典对象本身
- 注意:清除了字典对象本身的话,这个变量名就不能被引用了,也就是不能被调用了
- 语法:
del dict_obj
或者del dict_obj
- 没有返回值,用变量名接收还会报错
案例:将学生字典中的name删除
student_dict = {'name': 'jkey', 'age': 18,'habbies': ['play','eat']}
del student_dict['name']
print(student_dict) # ===> {'age': 18, 'habbyies': ['play', 'eat']}
del 一个字典对象本身
student_dict = {'name': 'jkey', 'age': 18,'habbies': ['play','eat']}
del student_dict
print(student_dict) # ====>NameError: name 'student_dict' is not defined
方式2: pop()
- 功能: 删除字典给定键 key 及对应的值
- 语法:
dict_obj.pop(key[,default])
key
为你要删除的键值对的键--key
default
:如果没有 key,返回 default 值
- 返回值为被删除的值。
key
值必须给出。 否则,返回default
值
案例:将学生字典中的name删除
student_dict = {'name': 'jkey', 'age': 18,'habbies': ['play','eat']}
name = student_dict.pop("name") # 将key=name的键值对在student_dict删除
print(name) # === > jkey
print(student_dict) # {'age': 18, 'habbyies': ['play', 'eat']}
方式3: popitem()
- 功能: 删除一个字典中的最后一个键值对
- 语法:
dict_obj.popitem()
- 返回的是被删除的最后一个
key:value
案例:随机删除学生字典中的一组键值对
student_dict = {'name': 'jkey', 'age': 18,'habbies': ['play','eat']}
student_dict.popitem() # 随机删除student_dict中的一组键值对
print(student_dict) # === > {'name': 'jkey', 'age': 18}
方式4: clear()
- 功能:清空字典的键值对
- 语法:
dict_obj.clear()
- 返回一个None
案例:清空学生字典
student_dict = {'name': 'jkey', 'age': 18,'habbies': ['play','eat']}
res = student_dict.clear() # 清空student_dict
print(student_dict) # ====> {}
print(res) # ===> None
是不是感觉干掉字典的方式很多,但字典真正用的多的还是增改查
还有一个很常见的就是和for循环之间的搭配啦
keys()方法
- 功能: 以列表返回一个字典所有的键
- 语法:
dict.keys()
- 返回值: 返回一个字典所有的键
案例:打印出学生字典中所有的键--key
student_dict = {'name': 'jkey', 'age': 18,'habbies': ['play','eat']}
for student_key in student_dict.keys(): # 遍历出字典student_dict中的所有的key
print(student_key)
for s_key in student_dict:
print(s_key)
'''
输出结果是一样的:
name
age
habbies
name
age
habbies
'''
注意:遍历一个字典默认返回的就是字典的键-key
values()方法
- 功能: 以列表返回字典中的所有值
- 语法:
dict.values()
- 返回值: 返回字典中的
所有值---value
。
案例:打印出学生字典中的所有的值
student_dict = {'name': 'jkey', 'age': 18,'habbies': ['play','eat']}
for s_value in student_dict.values(): # 遍历出字典student_dict中所有的值
print(s_value)
'''
输出结果为:
jkey
18
['play', 'eat']
'''
items()方法
- 功能: 以列表返回可遍历的(键, 值) 元组数组
- 语法:
dict.items()
- 返回值: 返回可遍历的(键, 值) 元组数组
案例:遍历出学生字典中的键值对
student_dict = {'name': 'jkey', 'age': 18,'habbies': ['play','eat']}
for key1, value1 in student_dict.items(): # 遍历student_dict 字典中的 所以键值对,返回(key,value)--->这个元组
print(key1, value1)
'''
输出结果:
name jkey
age 18
habbies ['play', 'eat']
'''
字典还有其他很多内置函数和方法哦
接着往下看
字典内置方法&函数(补充)
方法
copy()方法
- 功能: 对一个字典的浅复制
- 语法:
dict.copy()
- 返回值: 返回一个浅复制过来的字典
案例:将学生字典,浅copy一份出来
student_dict = {'name': 'jkey', 'age': 18,'habbies': ['play','eat']}
c_student_dict = student_dict.copy() # 对学生字典student_dict进行浅copy并绑定给变量名c_student_dict
print(c_student_dict) # ===> {'name': 'jkey', 'age': 18, 'habbies': ['play', 'eat']}
print(student_dict) # ===> {'name': 'jkey', 'age': 18, 'habbies': ['play', 'eat']}
深浅copy前面列表有介绍哦
有想深入了解的同学可访问:https://www.runoob.com/w3cnote/python-understanding-dict-copy-shallow-or-deep.html
fromkeys()方法
- 功能: fromkeys() 函数用于创建一个新字典,以序列
seq
中元素做字典的键,value
为字典所有键对应的初始值。 - 语法:
dict.fromkeys(seq[, value])
seq
表示 字典键值列表value
-- 可选参数, 设置键序列(seq)的值,一般为None
- 返回值: 该方法返回一个新字典
案例:创建一个新字典,内容的key为学生消息,值为None
res2 = {}.fromkeys(["name", 'age'], None)
res3 = {}.fromkeys(["name", 'age'], [])
print(res2) # {'name': None, 'age': None}
print(res3) # {'name': [], 'age': []}
print(res2['name']) # None
print(res3['name']) # []
需要注意的是:如果你将value初始值为一个列表,后面根据key改value会将整个字典全部的key对应的初始列表改变
has_key()方法(了解)
-
注意:Python 3.X 不支持该方法
-
功能: 判断键是否存在于字典中,如果键在字典 dict 里返回 true,否则返回 false
-
语法:
dict.has_key(key)
key
-- 要在字典中查找的键
-
返回一个布尔值
案例:判断学生字典中的是否有name
这个键
student_dict = {'name': 'jkey', 'age': 18,'habbies': ['play','eat']}
print(student_dict.has_key("name")) # True
setdefault()方法
- 功能: get()方法 类似, 如果键不存在于字典中,将会添加键并将值设为默认值
- 语法:
dict.setdefault(key, default=None)
key
查找的键值default
-- 键不存在时,设置的默认键值
- 返回值: 如果字典中包含有给定键,则返回该键对应的值,否则返回为该键设置的值
案例:判断学生字典中是否有性别(sex)的key,没有就添加,有就不动
student_dict = {'name': 'jkey', 'age': 18,'habbies': ['play','eat']}
# key不存在则添加key:value,key如果存在则什么都不做
# if "sex" not in student_dict:
# student_dict['sex'] = "male"
student_dict.setdefault("sex", "male") # 等用于上方的操作
print(student_dict) # ===> {'name': 'jkey', 'age': 18, 'habbies': ['play', 'eat'], 'sex': 'male'}
update()方法
- 功能: 把字典dict2的键/值对更新到dict里
- 语法:
dict.update(dict2)
- 返回值: 该方法没有任何返回值
案例:将水果字典添加到学生字典中
student_dict = {'name': 'jkey', 'age': 18}
goads_dict = {'apple': 2, 'pear': 3, 'peach': 5, 'name': 'liu'}
student_dict.update(goads_dict) # 将goads_dict的键值对添加到student_dict字典中,没有的键会将键值对直接添加在student_dict最后,如果student_dict字典中有
# 这个key-键 则会根据key-键 更新掉字典中的value
print(student_dict) # ==> {'name': 'liu', 'age': 18, 'apple': 2, 'pear': 3, 'peach': 5}
函数
序号 | 函数及描述 |
---|---|
1 | cmp(dict1, dict2) 比较两个字典元素。 |
2 | len(dict)计算字典元素个数,即键的总数。 |
3 | str(dict) 输出字典可打印的字符串表示。 |
4 | type(variable) 返回输入的变量类型,如果变量 |
cmp()方法(了解)
-
在python2所有版本中都可用,但在python3中该函数已经被删掉。
-
功能:用于比较两个字典元素。
-
方法语法:
cmp(dict1, dict2)
- dict1 -- 比较的字典
- dict2 -- 比较的字典
返回值:如果两个字典的元素相同返回0,如果字典dict1大于字典dict2返回1,如果字典dict1小于字典dict2返回-1。
案例:比较字典1和字典2元素大小
dict1 = {'name': 'jkey', 'age': 18}
dict2 = {'name': 'liu', 'age': 22}
print(cmp(dict1,dict2))
len()方法
- 功能: 计算字典元素个数,即键的总数
- 语法:
len(dict)
dict
-- 要计算元素个数的字典
- 返回值: 返回字典的元素个数
案例:打印出学生字典中的键的个数
student_dict = {'name': 'jkey', 'age': 18}
print(len(student_dict)) # ===> 2
str()方法
- 功能: 将值转化为适于人阅读的形式,以可打印的字符串表示。
- 语法:
str(dict)
- 返回值: 返回字符串
案例:将学生字典的键值对转换成字符串描述
student_dict = {'name': 'jkey', 'age': 18}
print(str(student_dict)) # ====> {'name': 'jkey', 'age': 18}
type()方法
- 功能: 返回输入的变量类型,如果变量是字典就返回字典类型。
- 语法:
type(dict)
- 返回的是一个数据类型
案例:判断student_dict
的数据类型
student_dict = {'name': 'jkey', 'age': 18}
print(type(student_dict)) # ===> <class 'dict'>
好啦,大概就这么多了,字典在之后的用处还是很多的,因为我们都知道我们要做的就是对数据的一些存取,字典不仅仅可以存多个值还方便通过key去取值,加油吧!!!!!骚年!!!!