浅拷贝与深拷贝
# copy()
dict1 = {
'a': 1,
'b': 2
}
# 浅拷贝
dict2 = {
'a': 1,
'b': 2
}
print(id(dict1), id(dict2))
id是不相同的。
a = 'ab'
b = 'ab'
print(id(a), id(b))
id是相同的。字符串是不可变类型。
浅拷贝
拷贝父对象,不会拷贝对象的内部的子对象
浅拷贝时,除了父对象的id不同,其余的所有都和拷贝的对象相同
对于不可变序列的浅拷贝,且分别对变量进行赋值的时候,这两个变量的id是一样的
对于不可变序列的拷贝时,其id是不变的。
dict2 = dict1.copy()
print(id(dict1), id(dict2))#浅拷贝方式一
import copy
dict2 = copy.copy(dict1)
print(id(dict1), id(dict2))#方式2
id是不相同的,cope相当于复制一份一摸一样的,但是地址是不一样的,相当于你拷贝一个文件把他复制粘贴到其他位置,位置改变了。
dict1 = {
'a': 1,
'b': [1, 2, 3]
}
dict2 = copy.copy(dict1)
print(id(dict1), id(dict2))
#dict1['b'][0] = 10 #修改字典
print(id(dict1['b']))
print(id(dict2['b']))
id是相同的,列表的id不包括在字典里面相当于在引用里面,相当于创建了快捷方式,如果在字典里进行更改,两个字典的内容都修改了。列表是可变类型数据,只是借用了地址。
深拷贝可以拷贝到更深层次的东西。浅拷贝只能拷贝到第一层的数据。
深拷贝
完全拷贝了父对象及其子对象
相当于又建立了一个一摸一样的对象,但是id不同
dict2 = copy.deepcopy(dict1)
print(id(dict1), id(dict2))
dict1['b'][0] = 10
print(id(dict1['b']))
print(id(dict2['b']))
print(dict1, dict2)
id不相同,且字典不会连同要拷贝的字典的改变而改变,当进行可变类型嵌套的时候,进行深拷贝,里面更深层次的可变数据都会拷贝。如果拷贝的是不可变类型id也是不会变的。
应用场景:
当你要对数据进行修改的时候,你又不想修改原来的数据,那么这个时候就需要用到深拷贝或者浅拷贝了。
遍历字典
- dict.keys() 获取字典中所有的键
- dict.values() 获取字典中所有的值
- dict.items() 获取字典中的键值对(项)
dict4 = {'name': '切尔西', 'birth': 1905, '类别': 'football club'}
print(dict4.keys())
print(dict4.values())
print(dict4.items())
for k, v in dict4.items():
print(k, '=', v )
集合
- 集合表现形式set 集合和列表非常相似
- 与列表的不同点
集合只能存储不可变对象(列表可以存储任何对象)
集合中存储的对象是无序的
集合不存在索引
集合不能出现重复元素(根据集合的特性可以做去重操作)
set表示集合 用{}表示
set1 = {1,2,3,5} - 可以通过set()来将序列和字典转换成集合
- len() 使用len()来获取集合中元素的数量
- add()像集合中添加元素
- update()将一个集合中的元素添加到另一个集合当中
- pop()随机删除集合中的一个元素一般是删除最后一个元素
- remove() 删除集合中指定的元素
- clear() 清空集合
# set.add() 添加元素
set1 = set()
set1.add(1)
print(set1)
# set.update() 讲一个集合添加到另一个集合中
set2 = {2, 3}
set1.update(set2)
print(set1)
# len() in not in
# del set1[0]集合没有索引
set3 = set1.copy()
print(set3)
# del set1
set1.clear()
print(set1)
注意
set1 = {} #这是空字典,不是空集合
set2 =set() #创建空集合
集合的强制转换应用:去重
list1=[1,1,2,2,3,4,4]
set3 = set(list1)
print(set3)
list1 =set3
print(list1)
集合的运算
- & 交集运算
- | 并集运算
- -差集运算
- ^ 亦或集
- <= 检查一个集合是否是另一个集合的子集
- < 检查一个集合是否是另一个集合的真子集
'>='检查一个集合是否是另一个集合的超集
'>'检查一个集合是否是另一个集合的真超集
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}
# 交集 查看重复的元素
print(set1 & set2)
# 并集
print(set1 | set2)
# 差集
print(set1 - set2)
# 异或集
print(set1 ^ set2)
bytes类型
bytes介绍
在Python3以后,字符串和bytes类型彻底分开了。字符串是以字符为单位进行处理的,bytes类型是以字节为单位处理的。
bytes数据类型在所有的操作和使用甚至内置方法上和字符串数据类型基本一样,也是不可变的序列对象。
Python3中,bytes通常用于网络数据传输、二进制图片和文件的保存等等。
bytes创建
可以通过调用bytes()生成bytes实例,其值形式为 b’xxxxx’,对于同一个字符串如果采用不同的编码方式生成bytes对象,就会形成不同的值。
a = b'hello'
print(type(a))
b = bytes('hello',encoding='utf8')
print(type(b))
# a和b都是bytes类型
bytes类型常用转换
在实际应用中,我们通常会将bytes类型与str类型做转换。
- 字节转为字符串
d = b'world'
print(d.decode())
print(type(d))
- 字符串转为字节
e = 'world'
print(type(e.encode()))
可变类型和不可变类型
可变类型
列表 字典 集合 值改变了,但是id不变
不可变类型
字符串 元组 值改变了 ,id就改变了
函数
函数简介
- 函数也是一个对象
- 函数用来保存一些可执行的代码,并且可以在需要时,对这些语句进行多次调用
语法
def 函数名([形参1,形参2,形参3....]):
代码块
注意:
函数名必须符合标识符的规范(可以包含字母、数字、下划线但是不能以数字开头)
print是函数对象 print()是调用函数
# 自定义函数
def fun():
print('这是我的第一个函数')
fun()
# 函数对象: fun
# 调用函数: fun()
函数的参数
形参和实参
- 形参(形式参数) 定义形参就相当于在函数内部声明了变量,但是并不是赋值
- 实参(实际参数)指定了形参,那么在调用函数时必须传递实参,实参将会赋值给对应的形参,简单来说有几个形参就要有几个实参
def fun(a, b): # 这个参数叫做形参 也叫形式上的参数
print(a + b)
fun(5, 26)# 实参 实际参数, 当你调用的时候传递实际参数
fun('你好', '切尔西')
函数的传递方式
- 定义形参时,可以为形参指定默认值。指定了默认值以后,如果用户传递了参数则默认值不会生效。如果用户没有传递,则默认值就会生效
def fun(a, b=0, c=0): # c=0 给形参指定默认值, 当没有传递实参的时候,使用默认值,当传递了参数,使用传递进来的参数
print(a)
print(b)
print(c)
fun(1, 2)
fun(1,2,3)
- 位置参数:位置参数就是将对应位置的实参赋值给对应位置的形参
def fun(a, b, b):
print(a)
print(b)
print(c)
- 关键字参数 : 关键字参数可以不按照形参定义的顺序去传递,而根据参数名进行传递
def fun(a=1, c=2, b=3):
print(a)
print(b)
print(c)
fun(1, 3, b=2)
# 位置传参和关键字传参混合使用, 位置传参必须放到关键字传参的前面
- 混合使用位置参数和关键字参数的时候必须将位置参数写到关键字参数前面去
def fun(a,b,c):
print(a)
print(b)
print(c)
fun(1,c=2,b=3)
fun(a=1,b=2,3) #直接报错,报错原因:位置传参在关键字传参后面
fun(1,3,b=2)#也会报错
fun(1,3,c=2)
一个实际参数对应一个形式参数,但是一个形式参数可以对应多个实际参数。
实参的类型
- 实参不管是什么类型的对象都可以
def fun1():
pass
def fun(a):
print(a)
b=1
b=[1,2,3]
b=True
b={'1':1}
b=fun1
fun(b)
易混淆
def fun2(a):
a=10
print(a)
b=1
fun2(b)
print(b)
# a=10 b=1
def fun2(a):
a[0]=10# 这里并没有给a重新赋值,只是做了个修改
print(a)
b=1
b=[1,2,3]
fun2(b)
print(b)
# a =[10,2,3] b=[10,2,3]
#不想修改外面的b
def fun2(a):
a[0]=10# 这里并没有给a重新赋值,只是做了个修改
print(a)
b=1
b=[1,2,3]
c = b.copy()#拷贝一份
fun2(c)#c变成了[10,2,3],但是b没有变
print(b)
不定长参数
- 定义函数时,可以在形参前面加一个*,这样这个形参可以获取到所有的实参,它会将所有的实参保存到一个元组中
- 带*号的形参只能有一个,可以和其他参数配合使用
- *形参只能接受位置参数,不能接受关键字参数
- **形参可以接收其他的关键字参数,它会将这些参数统一保存到字典当中。字典的key就是参数的名字,字典的value就是参数的值
- **形参只有一个,并且必须写在所有参数的后面
参数的解包
- 传递实参时,也可以在序列类型的参数前添加星号,这样它会自动的将序列中元素依次作为参数传递
- 要求序列中的元素的个数必须和形参的个数一致
作业
- 打印名片程序:输入姓名,电话号码,性别,最后打印出来名片
• 控制姓名长度为6-20
• 电话号码长度11
• 性别只能允许输入男或女
• 每一样信息不允许为空
username_1 = input("请输入你的名字:")
while True:
if len(username_1) < 6 or len(username_1) > 20:
print("名字输入错误,名字的长度只能为6-20!!!")
username_1 = input("请重新输入姓名:")
else:
print("名字输入正确!!!")
break
number_1 =input('请输入手机号码:')
#####################################################################################################
while True:
if number_1.isdigit() :
if len(number_1) == 11:
print("电话号码输入正确")
break
else:
number_1 =input("电话号码应为11位数字,请重新输入:")
else:
print('手机号码必须为数字',end=',')
number_1 = input('请重新输入手机号码:')
gender = input('请输入性别:')
#################################################################################################
while True:
if gender==str('男') or gender==str('女'):
print('性别输入正确')
break
else:
print('你输入的性别有误,请重新输入:')
gender = input('请重新输入性别:')
使用函数求前20个斐波那契数列
斐波那契数列:1,1,2,3,5,8,13,21…即: 起始两项均为1,此后的项分别为前两项之和
def fibo(i):
list1 = [1, 1]
for i in range (0,i):
list1.append(list1[i] + list1[i + 1])
print(list1)
fibo(18)#以列表输出前(i+2)项斐波那契数列
def fibo(i):
i = i-2
list1 = [1, 1]
for i in range (0,i):
list1.append(list1[i] + list1[i + 1])
print(list1)
fibo(20)
编写一段代码,定义一个函数求1-100之间所有整数的和,并调用该函数打印出结果
def a(c,d):
sum = 0
for i in range(c,d+1):
sum =sum+i
print(sum)
a(1,100)
#c为开始数,d为加到多少为止可以求c到d整数之间的和