函数基础
介绍
-
什么是函数
在编程的过程中,会出现代码冗余,可读性差,不易修改,所以出现了函数,函数类似一个工具,这个工具可以拿过来直接使用
-
定义一个函数
当python遇到 def 语句时候 ,会在内存中生成一个函数对象,并且这个函数是靠将函数名来引用,但是这个函数体
内部的语句只有在函数的调用的时候才会被执行,而函数调用结束了,就是函数返回时,函数执行完后内部变量将会被回收
def 函数名(形参1,形参2...):
'''函数的注释,描述函数的作用以及参数的类型'''
代码块
...
return # return可以获取函数执行后的返回值,也可以结束函数的运行
1.函数名的定义类似变量名
2.函数名加括号立即执行函数体代码 优先级最高
3.函数必须先定义再调用
func(10,20) # 报错,因为函数必须先 定义 在 引用(调用)
def func(x,y): # 定义函数
if x > y:
print(x) # return x 返回值 x
else:
print(y) # return y 返回值 y
func(2,5) # >>> 5 函数名加括号立即执行函数体代码
res = func(2,5)
print(res) # 返回值 None
print(func) # <function func at 0x0000027893BE2EA0> func 对应的是函数的内存地址
函数的返回值 return
-
不写 return 返回值 None
def func():
print('waller')
func() # >>> waller
res = func() # 定义变量接收给返回值
print(res) # >>> None
-
只写 return 返回值 None 除此之外还可以结束函数的运行
def func():
l = [1,2,3]
while True:
for i in l:
if i == 2: # 当 i == 2 时结束整个循环需要两个break,分别结束for和while
#break
return # 函数里的return可以结束整个函数,之后的代码永远不执行
print(i)
# else:
# print(i)
# break
res = func()
print(res) # >>> None
-
只写 return None
def func():
return None
res = func()
print(res) # >>> None
return 返回一个值,这个值可以是任意类型
def func1():
return 123
def func2():
return 'waller'
def func3():
return [1,'age']
def func4():
return (1,)
def func5():
return {'hubby':'read'}
def func6():
return {1,}
def func7():
return True
print(func1(),func2(),func3(),func4(),func5(),func6(),func7())
# >>> 123 waller [1, 'age'] (1,) {'hubby': 'read'} {1} True
return 返回多个值 返回的时一个元组,函数处理的结果不想被修改
def func1():
return 1,2,3,'a','b'
res1 = func1()
print(res1) # >>> (1, 2, 3, 'a', 'b')
def func2():
return [1,2],['a',1]
res2 = func2()
print(res2) # >>> ([1, 2], ['a', 1])
def func3():
return {'name':'waller'},{'age':20}
res3 = func3()
print(res3) # >>> ({'name': 'waller'}, {'age': 20})
# 返回多个值,不想函数处理成元组,可以自己动手加上数据类型符号,使多个值变成一个值
def func4():
return [{'name':'waller'},{'age':20}] # 利用return打印一个值的特点
res4 = func4()
print(res4) # [{'name': 'waller'}, {'age': 20}]
注意:
1.所有的函数都有返回值 2.只写return 或return None 不是为了返回值,是为了结束函数的运行
参数
形参:在函数定义阶段括号内的参数,这个形参相当于变量名,简称 形参 实参:在函数调用截断括号内的参数,这个参数相当于变量值,简称 实参
-
形参与实参的关系:
形参相当于变量名,实参相当于变量值
函数调用传参的阶段,就是实参变量值给形参变量名赋值的过程
注意:
形参和实参的绑定关系只有在函数调用阶段生效,函数运行完自动解除绑定关系
只有在函数内部有效,函数外部无影响
def func(x,y):
'''
函数的作用以及参数的类型
:param x:
:param y:
:return:
'''
print('waller')
return 'wong'
print(help(func)) # 打印出函数的注释
-
位置传参:
位置形参:在函数定义阶段,括号内从左到右依次写入的变量名较叫位置形参,调用时必须为其传值
位置实参:在函数调用阶段,对应位置形参依次在括号内填入的值,这些值会一一传给形参(类似变量名赋值)
def num_max(x,y): # x,y 是位置形参,需要传值
if x > y:
return x # 若x > y 返回值是 x
else:
return y # 否则 返回值是 y
res = num_max(2,6) # 2和6 是位置实参,按照x与y的位置传递参数 x = 2,y = 6
print(res) # 打印函数的返回值 >>> 6
res = num_max(5) # 报错 ,位置实参传参个数少于形参数
res = num_max(2,6,7) # 报错,位置实参传参个数多余形参数
-
关键字传参:
在函数调用阶段,按照形参的变量名 赋值
def num_max(x,y): # x,y 是位置形参,需要传值
if x > y:
return x # 若x > y 返回值是 x
else:
return y # 否则 返回值是 y
res = num_max(y=6,x=2) # 按关键字为形参传参
print(res) # >>> 6
res = num_max(y=6,x=2,x=1) # 报错,同一个形参不能被多次传值
res = num_max(2,y=6) # 位置参数和关键字参数同时使用
res = num_max(y=6,2) # 报错,关键字参数要在位置参数后面
注意:
位置传参和关键字传参和混合使用,但关键字传参要在位置传参的后面
同一个参数不能被多次赋值
-
默认参数:
定义:在函数定义阶段,形参(变量名)就已经被赋值了
在调用阶段,可以不为默认形参传值,默认使用定义阶段绑定的值
在调用阶段,如果为默认形参传值,就使用调用阶段传入的值
注意:定义阶段,默认形参要在位置形参的后面
应用场景: 当形参接收的值大多数是相同值的情况下,可以使用默认形参
def num_max(x,y=100):
if x > y:
return x
return y
res = num_max(50) # x = 50 y = 100 # 传入位置参数 50给形参x,形参y不传值,使用默认参数
print(res) # >>> 100
res1 = num_max(50,20) # x = 50 y = 20 # 传入位置参数 50给形参x,20给形参y
print(res) # >>> 50
def info(name,age,gender = 'male'): # gender = 'male' 是默认参数
print('name is {},age is {},gender is {}'.format(name,age,gender))
info('waller',20) # >>> name is waller,age is 20,gender is male
info('wong',24) # >>> name is wong,age is 24,gender is male
info('tuan',22,'female') # >>> name is tuan,age is 22,gender is female
-
可变长参数
形参中的 * 可以将实参中多余的位置参数组成元组的形式赋值给形参中*后面的变量名,不能接收关键字实参
实参中的 * 可以将实参中除字典的容器类型数据打散,依次赋值给形参
形参中的 ** 可以将实参中多余的key=value的关键字形式实参存成字典的形式 赋值给形参中** 后面的变量名,不能接收其他容器类型的实参(俗称封装)
实参中的 ** 会将实参中的字典类型数据,按照key=value的关键字传参的形式赋值给形参(俗称打散)
python 推荐*和**写法:
def func(*args,**kwargs): # 调用者按照正确的传参方式无论怎么传都可以接受
print(args,kwargs)
# 形参中的 *
def func(x,y,*z):
print(x,y,z)
func(1,2,3,4,5,6,) # >>> 1 2 (3, 4, 5, 6) z = (3, 4, 5, 6)
# 实参中的 *
def func(x,y,z):
print(x,y,z)
func(*[1,2,3,]) # >>> 1 2 3
def func(x,y,z):
print(x,y,z)
func(*('a','b',1)) # >>> a b 1
def func(x,y,z):
print(x,y,z)
func(*{'a',(1,2),5})
def func(x,y,*z):
print(x,y,z)
func('a',5,*[1,2,3]) # a 5 (1, 2, 3)
# 形参中 **
def func(x,**y):
print(x,y)
func(x='a',y='b',z='c',d=1,e=2) # y = {'y': 'b', 'z': 'c', 'd': 1, 'e': 2}
# >>> a {'y': 'b', 'z': 'c', 'd': 1, 'e': 2}
# 实参中的 **
def func(x,y):
print(x,y)
d = {'x':'waller','y':20}
func(**d)
函数是第一类对象
-
函数名可以被传递(类似变量)
name = 'waller'
ures_name = name # 变量名的传递
print(ures_name) # >>> waller
def func():
print('name is waller')
print(func) # 打印的是函数体代码的内存地址 <function func at 0x000002EF3AA02EA0>
print(id(func)) # 打印的是函数名在内存里的地址 3226504015520
f = func # func对应的函数内存地址也赋值给f
print(f) # 打印的是函数体代码的内存地址 <function func at 0x000002EF3AA02EA0>
f() # 调用函数,等价与func()
-
函数名可以被当作参数传递给其他函数
def func():
print('from func')
def info(regs):
print(regs) # <function func at 0x000001A378C62EA0>
regs() # from func
print('from info') # from info
info(func)
-
函数的名可以被当作函数的值被返回
def func():
print('from func')
def info():
print('from info')
return func
info() # >>> from info 是打印函数运行的结果,并且由返回值可接收
res = info() # >>> from info # 函数的返回值赋值给变量 res
print(res) # >>> <function func at 0x000002C27E772EA0> # 等价于 print(func)
res() # >>> from func # 等价于 func()
-
函数名可以当作容器类型数据里的元素
def func():
print('from func')
print(func()) # 优先运行func()函数,运行结果是from func,有返回值None被print打印了出来9
l = [1,2,func,func()] # 容器类型数据是把func()函数的 返回值 放入其中,而不是函数运行结果
print(l) # >>> [1, 2, <function func at 0x0000024143502EA0>, None]
函数的嵌套
在函数内部调用其他函数,可以使复杂的逻辑简单化
def my_max(x,y): # 定义可以比较两个数大小的函数
if x > y:
return x
return y
# print(my_max(2,5)) # >>> 打印出函数运行的返回值
def my_max1(a,b,c,d):
res1 = my_max(a,b) # 接收两个数比较后的返回值
res2 = my_max(res1,c)
res3 = my_max(res2,d)
return res3 # 接收最终的返回值
print(my_max1(2,4,6,8)) # >>> 8 # 打印出四个数比较大小的返回值
名称空间
存放变量名的地方,存放的使变量名与变量地址绑定关系的地方 要想访问一个值,必须要到名称空间找到变量名才能访问到变量值
-
名称空间分类
内置名称空间:python解释器提前定义好的名字存在了内置名称空间(len,max,print,range...)
全局名称空间:文件级别的代码,一般是程序员按照变量名命名规范所起的变量名
局部名称空间:函数体内创建的变量名都属于局部名称空间
-
名称空间生命周期
1.内置名称空间:python解释器启动创建,python解释器关闭自动销毁
2.全局名称空间:右键运行py文件创建,py文件运行完毕自动销毁
3.局部名称空间:函数调用时创建,函数运行结束立即销毁(动态创建,动态销毁)
-
名称空间查找顺序
先确定当前位置(*****):
如当前位置在全局:全局 >>> 内置
如当前位置在局部;局部 >>> 全局 >>> 内置
x=111
def outer():
def inner():
print('from inner',x) # 函数在定义阶段名字的查找顺序就已经确定了
return inner
f=outer()
def func():
x=333
f() # 不会应为函数的调用位置变化而改变
func() # >>> from inner 111
函数在定义阶段名字的查找顺序就已经确定了,不会应为函数的调用位置变化而改变(*****)
函数在定义时还没有生产函数的名称空间,只有调用时才会生产
作用域
全局作用域:全局生效
局部作用域:局部生效
global:局部修改全局,如修改多个,用逗号隔开
# 局部修改全局
name = 'waller'
age = 20
def func():
global age,name # 声明
age = 22
name = 'wong'
print(name,age)
func() # wong 22
print(name) # wong
print(age) # 22
nonlocal:局部修改局部,如修改多个,用逗号隔开
# 局部修改局部
def func():
x = 1
def info():
nonlocal x
x = 2
info()
print(x)
func() # >>> 2
上一篇: Spring5——事务
下一篇: 我知道微信朋友圈那个根本不是你