1. 浅复制
- copy() 方法可以用于对序列进行浅复制:
复制与赋值是有区别的,= 赋值运算符使两个变量指向同一个对象,不是真正意义上的复制。
而在大多数情况下,我们通常希望复制对象后,修改复制的对象不会影响原有的对象。
接下来看示例代码
d1 = {'a': 1, 'b': 2, 'c': 3}
# = 赋值运算符使两个变量指向同一个对象
d2 = d1
# 使用copy方法进行浅复制
d3 = d1.copy()
# 分别修改d2和d3
d2['a'] = 10
d3['a'] = 100
print('d1 = ', d1, 'id(d1): ', id(d1))
print('d2 = ', d2, 'id(d2): ', id(d2))
print('d3 = ', d3, 'id(d3): ', id(d3))
运行结果:
- 浅复制的局限性:
浅复制只会复制序列本身,如果序列中还有另外一个可变序列是不会复制的。
上述特性对字典和列表都是适用的。
d1 = {'name': {'first': 'Smith', 'second': 'John'}, 'age': 20, 'id': 123}
d2 = d1.copy()
d2['name']['second'] = 'Ban'
print('d1 = ', d1)
print('d2 = ', d2)
运行结果:
拓展:深复制
import copy
d1 = {'name': {'first': 'Smith', 'second': 'John'}, 'age': 20, 'id': 123}
d2 = copy.deepcopy(d1) # 使用深复制
d2['name']['second'] = 'Ban'
print('d1 = ', d1)
print('d2 = ', d2)
运行结果:
使用深复制会复制整个对象,包含第二层可变序列。
2. 字典的遍历
我们主要可以通过3种方式对字典进行遍历:
- keys() 该方法返回字典所有的key;
- values() 该方法返回⼀个序列,序列中保存有字典的值;
- items() 该方法会返回字典中所有的项,它返回⼀个序列,序列中包含有双值子序列,双值分别是字典中的key和value。
d1 = {'name': {'first': 'Smith', 'second': 'John'}, 'age': 20, 'id': 123}
# 通过keys方法遍历
for k in d1.keys():
print('key = ', k, ', value = ', d1[k])
# 通过values方法遍历
for v in d1.values():
print('value = ', v)
# 通过items方法遍历
for k, v in d1.items():
print('key = ', k, ', value = ', v)
运行结果:
3. 集合的快速入门
3.1 集合简介
集合表现形式set,集合和列表非常相似。
集合与列表的不同点:
- 集合中只能存储不可变对象;
- 集合中存储的对象是无序的(不是按照元素的插入顺序保存的);
- 集合中不能存储重复的元素。
s = {10, 2, 3, 4, 5, 2, 1, 3, 2}
print(s, type(s))
s = {[1, 2, 3], [4, 5, 6]}
print(s)
# 错误信息
TypeError: unhashable type: 'list'
运行结果:
使用 {}或者set() 创建集合,set() 可以将序列和字典转化为集合。
如果使用 set() 将字典转化为集合,只会包含字典的键。
因为集合存储元素是无序的,所以不能通过索引查找元素。
s = set([1, 2, 3, 4, 1, 2, 3, 2, 3, 5])
print(s)
s = set({'a': 1, 'b': 2, 'c': 3})
print(s)
print(s[0])
# 错误信息
TypeError: 'set' object does not support indexing
运行结果:
集合的使用场景:如果需要对数据进行去重,可以考虑使用集合。
3.2 集合的使用方法
- 使用 in not in 来检查集合中的元素;
- add() 向集合中添加元素;
- update() 将一个集合中的元素添加到另一个集合;
- pop() 随机删除集合中的一个元素,并将删除的元素返回;
- remove() 删除集合中指定的元素;
- clear() 清空集合中的元素。
s = {'python', 1, 2, 3, 'hello'}
print('in的使用:', 'python' in s)
print('not in的使用:', 4 not in s)
s.add(10)
print('使用add添加集合元素: ', s)
s.update({'John', 5})
print('使用update添加集合元素: ', s)
result = s.pop()
print('使用pop删除集合元素: ', s)
print('被删除的元素为: ', result)
s.remove('hello')
print('使用remove删除指定元素: ', s)
s.clear()
print('使用clear清空集合元素: ', s)
运行结果:
3.3 集合的运算
- 交集运算 &
- 并集运算 |
- 差集运算 -,存在顺序关系,s1 - s2 返回 s1 中去除 s1 与 s2 交集后的元素;
- 亦或运算 ^,不存在顺序关系,返回两个集合中去除交集的元素;
- <= 检查⼀个集合是否是另⼀个集合的子集;
- < 检查⼀个集合是否是另⼀个集合的真子集;
- >= 检查⼀个集合是否是另⼀个集合的超集;
- > 检查⼀个集合是否是另⼀个集合的真超集。
s1 = {1, 2, 3, 4, 5}
s2 = {3, 4, 5, 6, 7}
print('交集运算:', s1 & s2)
print('并集运算:', s1 | s2)
print('s1-s2 差集运算:', s1 - s2)
print('s2-s1 差集运算:', s2 - s1)
print('亦或运算:', s1 ^ s2)
s1 = s1 & s2
print('s1 < s2: ', s1 < s2)
print('s1 <= s2: ', s1 <= s2)
运行结果:
4. 函数
函数也是一个对象,类型为function。
面向对象三大特性:封装、继承、多态。
函数可以用来保存一些可执行的代码,并且可以在需要的时候,多次对这些代码调用
函数基本语法:
def 函数名():
代码块
# 调用函数
函数名()
print是函数对象,print() 表示调用函数。
4.1 函数的参数
关于函数参数的知识点:
- 在定义函数的时候,可以在函数名之后的括号中定义数量不等的形参;
- 定义多个形参要用逗号隔开;
- 形参(形式参数),相当于在函数内部声明了变量,不是赋值;
- 实参(实际参数),如果函数定义的时候只定义了形参,name在调用的时候也必须传递实参;
- 实参将会赋值给对应的形参,简单来说有几个形参就要有几个实参。
def fn(a, b):
print('a = ', a)
print('b = ', b)
# 调用函数fn
fn()
# 错误信息
TypeError: fn() missing 2 required positional arguments: 'a' and 'b'
# 调用函数fn时传递实参
fn(1, 2)
# 结果:
a = 1
b = 2
定义一个简单地函数,可以用来求任意两个数的和。
# 定义函数: 求任意两个数的和
def myadd(a, b):
print(f'{a} + {b} = {a + b}')
myadd(56, 72)
运行结果:
4.2 参数的传递方式
- 定义形参时,可以为形参指定默认值。指定了默认值以后,如果用户传递了参数则默认值不会生效。如果用户没有传递,则默认值就会生效。
def fn(a, b, c=10):
print('a = ', a)
print('b = ', b)
print('c = ', c)
print('传递等量参数:')
fn(1, 2, 3)
print('传递两个参数:')
fn(3, 4)
运行结果:
函数的传递方式有位置传参和关键字传参。
- 位置参数:位置参数就是将对应位置的实参赋值给对应位置的形参;
- 关键字参数 : 关键字参数可以不按照形参定义的顺序去传递,而根据参数名进行传递;
- 混合使用位置参数和关键字参数的时候必须将位置参数写到关键字参数前面去。
def fn(a=1, b=2, c=3):
print('a = ', a)
print('b = ', b)
print('c = ', c)
print('位置传参:')
fn(10, 20, 30)
print('使用关键字传递参数:')
fn(b=20)
print('混合传参:')
fn(10, b=40)
运行结果:
混合传参时,若使用关键字参数之前必须先保证位置参数已经传参。
def fn(a=1, b=2, c=3):
print('a = ', a)
print('b = ', b)
print('c = ', c)
print('混合传参2:')
fn(b=40, 50)
# 错误信息
SyntaxError: positional argument follows keyword argument
运行结果: