第十三天 |
一、函数
学习目标:
1、变量作用域
2、多函数程序执行流程
3、函数的返回值
4、函数的参数
5、拆包和交换两个变量的值
6、引用
7、可变和不可变类型
二、变量作用域
1、变量作用域指的是变量生效的范围:主要分为局部变量和全局变量
2、局部变量:
2-1、生效范围:函数体内,只在函数体内生效
2-2、写法:只能写在函数体内
2-3、作用:在函数体内部,临时保存数据,即当函数调用完成后,则销毁局部变量
3、全局变量:
3-1、指的是在函数体内、外都能生效的变量
3-2、函数内外都可
3-3、作用:可以方便快速的多次访问
局部变量
定义在函数体内部,临时保存
# 定义一个函数,声明一个变量,函数体内部、外面访问
def testA():
a = 20
print(a)
testA()
# print(a) # NameError: name 'a' is not defined,因为a 是在函数体内声明的变量
全局变量
全局变量,函数体内外都可以生效
# 定义全局变量a
a = 100
print('1',a)
def testA():
print('2', a)
print(a)
print('3', a)
testA()
print('4',a)
运行结果
1 100
2 100
100
3 100
4 100
三、修改全局变量
使用方法
直接在想要修改的函数体内部,加上:
global 变量名
。
举例:global a关键字声明a是全局变量,然后再更改a的值,可以在函数内输出,也可以在函数调用后输出,按照自己的需求。
用于:函数体内部修改函数变量,函数调用时,输出修改的值。
a = 100
print(a) # 1、第一步
def testA():
print('A内部',a)
print(',,,',a) # 2、第二步
def testB():
global a
a = 50
print('B函数体内修改全局变量后',a)
testA() # 第三步
print('A调用后',a) # 第四步
testB() # 第五步
print('B函数体内修改全局变量,调用后',a) # 第六步
运行结果
100
,,,
100
A内部 100
A调用后 100
B函数体内修改全局变量后 50
B函数体内修改全局变量,调用后 50
总结
1、如果直接在函数内部将变量a赋值,a不是全局变量的修改,而是相当于在函数内部声明了一个新的局部变量
2、修改全部变量的方法:加声明:global,声明关键字a是全局变量
3、程序是从上往下执行的,遇到函数调用才会输出
四、多函数执行流程
1、公用全局变量
总结:只要按照顺序执行的函数调用内的函数体修改了全局变量,
那么在函数调用之后的函数调用和输出的相关全局变量的值都会发生改变
a = 100
print(a) # 1、第一步
def testA():
global a
a = 50
print('A内部',a)
print(',,,',a) # 2、第二步
def testB():
print('B内部',a)
testA() # 第三步
print('A调用后',a) # 第四步
testB() # 第五步
print('B调用后',a) # 第六步
运行结果
100
,,,
100
A内部 50
A调用后 50
B内部 50
B调用后 50
2、返回值作为参数传递(用法)
用法:两个函数,一个有返回值,用变量接收返回值;另一个将接收返回值的变量值作为参数传递到另一个函数。
注意:两个函数都用到了函数调用,没有函数调用就不算是一个完整的函数的使用!
def testA():
return 50
def testB(num):
print(num)
# 用变量保留函数的返回值
result = testA()
# 该变量作为参数传入另一个函数testB()
testB(result) # 50
3、快速书写代码
函数2使用函数1的返回结果作为参数,打印出来
你好,阳光
def test1():
return '阳光'
def test2(num):
print('你好,',num)
result = test1()
test2(result)
五、函数的返回值(,隔开)
1、函数有多个返回值,不能直接书写多个return!因为一遇到return就会退出当前函数,不会执行return下面代码的操作!
2、函数有多个返回值的写法:将返回值用**“,”隔开!!!默认会返回一个元组**
3、return后面可以连接列表、元组、字典,(不常见的集合、字符串),可以返回多个值
# 不打印的话是没有值的!!除非要调用的函数体内有print
# 一个函数多个返回值的写法
def return_num():
# return 1,2 # (1, 2)
# return (10,20) # (10, 20)
# return [10,20] # [10, 20]
# return {'name':'Rose','age':20} # {'name': 'Rose', 'age': 20}
# return (10,20),{'name':'Rose','age':20} # ((10, 20), {'name': 'Rose', 'age': 20})
# return '1234','5678' # ('1234', '5678')
return {1,2,3,4,5} # set {1, 2, 3, 4, 5}
result = return_num()
print(result)
六、函数的参数
函数的参数的写法4种
1、位置参数:调用函数时根据函数定义的参数的位置来传递参数,传递和定义参数的顺序及个数必须一致
2、关键字参数:通过“键=值”的形式来传递参数,若有位置参数,那么位置参数必须写在关键字参数之前
3、缺省参数:形参=,所以的参数都必须在默认参数之前
4、不定长参数:包裹位置传递、包裹关键字传递
4的注意:包裹位置参数传递,里面只能有位置参数,不能有其它!!
包裹关键字参数传递,里面只能有关键字参数,不能有其它!!
综上:无论是包裹位置传递还是包裹关键字传递,都是一个“组包”的过程,即变为一个整体,如(‘Jer’, 18, ‘女’)何{‘name’: ‘Tom’, ‘age’: 20}
1、函数的位置参数
概念:调用函数时根据函数定义的参数的位置来传递参数,即实参和形参一一对应!!!
注意事项:传递和定义参数的顺序及个数必须一致,否则会导致数据无意义或者报错缺失的参数
# 函数的三个参数name,age,gender
def user_info(name,age,gender):
print(f'您的姓名是{name},性别是{gender},年龄是{age}')
user_info('Tom',20,'男')
# print里面的输出语句的格式化字符串可以随意顺序
2、关键字参数
概念:通过“键=值”的形式来传递参数,在函数调用中可以无视实参形参必须一一对应的弊端,可以使函数更便于使用
注意:1、函数调用时,若有位置参数,那么位置参数必须写在关键字参数之前,(关键字参数不分先后)
2、写法:“键=值”,键不需要加引号,直接书写,例gender='女'
def user_info(name,age,gender):
print(f'您的姓名是{name},年龄是{age}岁,性别是{gender}')
user_info('Tom',age=20,gender='男') # 您的姓名是Tom,年龄是20岁,性别是男
user_info('Tomy',gender='女',age=20,) # 您的姓名是Tomy,年龄是20岁,性别是女
3、缺省参数
也叫默认参数,为参数提供默认值,节约用户时间,提高用户效率
写法:直接在形参位置,想要默认参数的位置写,形参=。
注意:1、所以的参数都必须在默认参数之前
2、函数调用时,若不修改默认缺省参数的值,则会使用这个默认参数
def user_info(name,age,gender='男'):
print(f'您的姓名是{name},年龄是{age}岁,性别是{gender}')
user_info('Tom',age=20) # 您的姓名是Tom,年龄是20岁,性别是男
user_info('Jer',18,gender='女') # 您的姓名是Jer,年龄是18岁,性别是女
4、不定长参数
也叫作可变参数。用于不确定调用的时候会传递多少个参数(不传参也可以)的场景
(用于不确定调用多少个参数的时候)(不确定参数)
两种不定长参数的写法:
1、包裹位置传递,接收所有的位置参数,返回一个元组,可以传参数,也可以不传参数
2、包裹关键字传递
3、注意事项:包裹位置参数传递,里面只能有位置参数,不能有其它!!包裹关键字参数传递,里面只能有关键字参数,不能有其它!!
4.1不定长参数之位置参数-包裹位置传递(*args)
接收所有的位置参数,返回一个元组,可以传参数,也可以不传参数
def user_info(*args):
print(args)
user_info() # ()
user_info('Tom') # ('Tom',)
user_info('Jer',18,'女') # ('Jer', 18, '女')
4.2不定长参数之关键字参数-包裹关键字传递(**kwargs)
包裹关键字传递,接收所有的关键字参数,返回一个字典,也可以不传参数
def user_info(**kwargs):
print(kwargs)
user_info() # {}
user_info(name='Tom') # {'name': 'Tom'}
user_info(name='Tom',age=20) # {'name': 'Tom', 'age': 20}
注意:
包裹位置参数传递,里面只能有位置参数,不能有其它!!
包裹关键字参数传递,里面只能有关键字参数,不能有其它!!
1、 user_info(name=‘Jer’,18,‘女’) # 错误1:(‘Jer’, 18, ‘女’) # positional argument follows keyword argument关键字参数必须要在位置参数之后
2、user_info(18,‘女’,name=‘Jer’,) # 错误2:user_info() got an unexpected keyword argument 'name’没有关键字参数
3、user_info(‘Tom’,age=20) # user_info() takes 0 positional arguments but 1 was given,使用包裹关键字参数传递时,没有位置参数,却被传入位置参数,所以报错
七、拆包和交换变量值
7.1拆包(主要讲元组、字典)
组包:将零散的数据整合到一起,
拆包:把一个整体数据单独拆开
拆包:元组
拆包的参数和函数里面的返回值一一对应
def return_num():
return 1,2
num1,num2 = return_num()
print(num1,num2) # 1 2
print(num1) # 1
print(num2) # 2
衍生,拆包的参数和返回值一一对应
def return_num():
return 1,2
num2,num1=return_num()
print(num1) # 2
print(num2) # 1
拆包:字典
使用变量接收,另外再用查询
字典名[key]
,取出来字典的key
dict1 = {'name':'Tom','age':20}
a,b = dict1
# print(a) # name
# print(b) # age
print(dict1[a],dict1[b]) # Tom 20
拆包:字符串
str = '字符串进行拆包','也可以哦'
a,b= str
print('a:',a) # a: 字符串进行拆包
print('b:',b) # b: 也可以哦
7.2交换变量值
方法一借助第三变量存储数据
c=0
a,b=10,100
c=a
a=b
b=c
print('a=',a,'b=',b) # a= 100 b= 10
方法二化简写法(推荐)
推荐,直接交换即可,把b的值给a,把a的值给b
a,b=1,2
a,b=b,a
print('a=',a,'b=',b) # a= 2 b= 1
交换多个数据
将想要交换的数据,写到对应的位置即可!!
a,b,c=1,2,3
a,c,b=b,a,c
print('a=',a,'b=',b,'c=',c) # a= 2 b= 3 c= 1
八、引用
8.1了解引用
1、可变、不可变数据类型,数据在传递的过程中,都是通过引用传递的
2、id指的是那块内存的地址标识
3、不可变类型的数据,若是修改了数据的值,传递过程中,会开辟一个新的内存存储,发生变化。
4、可变类型的数据,若是修改了值,原来的内存地址会发生更改,并保持一致!
5、可变数据类型:列表、字典、集合
6、不可变数据类型:整型、浮点型、字符串、元组
引用之不可变类型
a = 1
b = a
print(id(a)) # 1739746320
print(id(b)) # 1739746320
# 修改a的值
a = 10
print(id(a)) # 1739746608
print(id(b)) # 1739746320
引用之可变类型
可变数据类型,数据在传递的过程中,是通过引用传递的
aa = [11,23]
bb = aa
print(id(aa)) # 1831936741960
print(id(bb)) # 1831936741960
# aa.append(30)
aa[0] = 22
print(aa) # [22,23]
print(id(aa)) # 1831936741960
print(id(bb)) # 1831936741960
8.2引用当作实参去传递
引用不可变数据作为实参(OK)
def testA(a):
print(a)
print(id(a))
a += a
print(a)
print(id(a))
b = 100
testA(b)
# 100
# 1739749488
# 200
# 1739752688
引用可变数据作为实参(OK)
def testA(a):
print(a)
print(id(a))
a += a
print(a)
print(id(a))
c = [100,200]
testA(c)
# [100, 200]
# 1535662117448
# [100, 200, 100, 200]
# 1535662117448
九、可变和不可变类型
概念:可以直接修改原数据,是可变类型,否则,不可变类型
可变类型:列表、字典、集合
不可变类型:整型、浮点型、字符串、元组
十、总结
变量作用域
1、局部变量:只在函数体内生效
作用:在函数体内部,临时保存数据,即当函数调用完成后,则销毁局部变量
2、全局变量:在函数体内、外都能生效的变量
作用:可以方便快速的多次访问
函数多返回值写法
return 表达式1,表达式2…
函数的参数
-
1、位置参数:调用函数时根据函数定义的参数的位置来传递参数,传递和定义参数的顺序及个数必须一致
-
2、关键字参数:通过“键=值”的形式来传递参数,若有位置参数,那么位置参数必须写在关键字参数之前,书写顺序可以不一致
-
3、缺省参数:即默认参数,在形参的位置写,形参=,所以的参数都必须在默认参数之前
-
4-1、不定长位置参数
包裹位置参数传递,里面只能有位置参数,不能有其它!!返回一个元组! -
4-2、不定长关键字参数
包裹关键字参数传递,里面只能有关键字参数,不能有其它!!返回一个字典! -
综上:无论是包裹位置传递还是包裹关键字传递,都是一个“组包”的过程,即变为一个整体,如(‘Jer’, 18, ‘女’)何{‘name’: ‘Tom’, ‘age’: 20}
引用
Python中,数据的传递都是通过引用