函数语法
函数:
定义语法:
def 函数名(参数1,参数2):
'''注释文档'''
函数体
return
函数定义:
- 申请内存空间保存函数体代码
- 将上述内存地址绑定函数名
- 定义函数不会执行函数体代码,但会检测语法
三种函数定义形式
无参函数: def fun(): 函数体 有参函数: def fun(x,y): 函数体 空函数: def fun(): pass/...(表示占位符)
例子:
#无参函数:
def fun():
print("hello")
fun()
#有参函数:
def fun(x, y):
res = x + y
return res
add = fun(1, 2)
print(add)
#空函数:
def fun():
pass
调用函数
- 通过函数名找到内存地址
- 加括号就是触发函数体代码执行
三种调用形式
- 语句形式:只加括号调用函数
- 表达式形式
- 函数调用可以当参数
#语句形式
def fun():
print("hello")
fun()
#表达形式:
def fun(x, y):
res = x + y
return res
add = fun(1, 2)
print(add)
#调用函数当参数:
def fun(x, y):
res = x + y
return res
add = fun(fun(1, 2), 10)
print(add)
返回值:当函数体执行 return 时表示终止函数运行,并且会将 return 后的值当做本次运行结果返回
1.None:函数体没有return 或者 return None return 2. 返回一个值:return 3.返回多个值: 多个值之间逗号分隔 return 返回元组(这个元组是默认的不能修改)
实参与形参
形参:在定义函数时的参数
实参:在调用函数时的参数
形参与实参的关系:
- 在调用时实参会绑定形参
- 绑定关系只能在函数体内使用
- 实参与形参的绑定关系只有调用时生效,而调用结束后则解除绑定关系
实参传值:
# 形式一:
func(1, 2)
# 形式二:
a = 1
b = 2
func(a, b)
# 形式三:
func(int('1'), 2)
形参与实参的使用
位置参数
位置形参:在函数定义时,按照从左到右的顺序定义
特点:必须被传值,形参有几个值,就要传入几个值
位置实参:调用时按照从左到右的顺序依次传值
特点:按照形参顺序对应传值
def func(x,y):
print(x,y)
func(1,2)
关键字参数
关键字形参:在函数调用时按照 keys 与 value 的形式传值
特点:根据“变量名”传值且可以不按照顺序传值
def func(x,y):
print(x,y)
func(y=2,x=1)
位置参数与关键字参数的混合使用:
1,位置实参必须放在关键字实参前
func(1,y=2)
2,不能同时给同一个形参传多个值
func(1,y=2,x=3) #错误的演示
默认参数:在定义函数时就已经被赋值的形参
特点:定义时被赋值了调用时就可以不用赋值,当然也可以在重新赋值
def func(x,y=3):
print(x,y)
func(x=1,y=44444)#y在形参定义时已经赋值了,但是调用函数时也可以在重新赋值
def register(name,age,gender='男'):
print(name,age,gender)
register('三炮',18)
register('二炮',19)
register('大炮',19)
register('没炮',19,'女')
位置参数与默认参数的混合使用
1,位置形参必须在默认形参的左边
def func(y=2,x):
pass
2,默认参数的值是在函数定义赋值的,准确的说是赋予了内存地址
m=2
def func(x,y=m): # y=>2的内存地址
print(x,y
m=3333333333
func(1)
3,默认值可以指定任意类型,但是不推荐使用可变类型,因为这样会使整个函数的逻辑关系变的混乱。
函数理想的状态:函数的调用只跟函数本身有关系,不被外界代码影响。
def func(x,y,z,l=None):
if l is None:
l=[]
l.append(x)
l.append(y)
l.append(z)
print(l)
func(1,2,3)
func(4,5,6)
new_l=[111,222]
func(1,2,3,new_l)
可变长参数
可变长度的参数(*与**的用法)
可变长度指的是在调用函数时,传入的值(实参)的个数不固定
而实参是用来为形参赋值的,所以对应着,针对溢出的实参必须有对应的形参来接收
可变长度的位置参数
I:*形参名:用来接收溢出的位置实参,溢出的位置实参会被*保存成元组的格式然后赋值紧跟其后的形参名
*后跟的可以是任意名字,但是约定俗成应该是args
def my_sum(*args):
res=0
for item in args:
res+=item
return res
res=my_sum(1,2,3,4,)
print(res)
II: *可以用在实参中,实参中带*,先*后的值打散成位置实参
def func(x,y,z):
print(x,y,z)
# func(*[11,22,33]) # func(11,22,33)
# func(*[11,22]) # func(11,22)
l=[11,22,33]
func(*l)
III: 形参与实参中都带*
def func(x,y,*args): # args=(3,4,5,6)
print(x,y,args)
func(1,2,[3,4,5,6])
func(1,2,*[3,4,5,6]) # func(1,2,3,4,5,6)
func(*'hello') # func('h','e','l','l','o')
可变长度的关键字参数
I:**形参名:用来接收溢出的关键字实参,**会将溢出的关键字实参保存成字典格式,然后赋值给紧跟其后的形参名
**后跟的可以是任意名字,但是约定俗成应该是kwargs
def func(x,y,**kwargs):
print(x,y,kwargs)
func(1,y=2,a=1,b=2,c=3)
II: **可以用在实参中(**后跟的只能是字典),实参中带**,先**后的值打散成关键字实参
def func(x,y,z):
print(x,y,z)
func(*{'x':1,'y':2,'z':3}) # func('x','y','z')
func(**{'x':1,'y':2,'z':3}) # func(x=1,y=2,z=3)
III: 形参与实参中都带**
def func(x, y, **kwargs):
print(x, y, kwargs)
func(y=222, x=111, a=333, b=444)
func(**{'y': 222, 'x': 111, 'a': 333, 'b': 4444})
混用*与**:*args必须在**kwargs之前
def index(x, y, z):
print('index=>>> ', x, y, z)
def wrapper(*args, **kwargs): # args=(1,) kwargs={'z':3,'y':2}
index(*args, **kwargs)
# index(*(1,),**{'z':3,'y':2})
# index(1,z=3,y=2)
wrapper(1, z=3, y=2)
命名关键字参数
命名关键字参数:在定义函数时,*后定义的参数,如下所示,称之为命名关键字参数
特点:命名关键字实参必须按照key=value的形式为其传值
def func(x,y,*,a,b):
print(x,y)
print(a,b)
func(1,2,b=222,a=111)
组合使用
形参混用的顺序:位置新参,默认形参,*args,命名关键字形参,**kwargs
def func(x,y=111,*args,z,**kwargs):
print(x)
print(y)
print(args)
print(z)
print(kwargs)
名称空间namespacs:存放名字的地方,对栈区的划分,可以在栈区中存放相同的名字
内置名称空间
存放的名字:python解释器内置名字
存活周期:python解释器启动则产生,python解释器关闭则销毁
全局名称空间
存放的名字:只要不是函数内定义、也不是内置的,剩下的都是全局名称空间的名字
存活周期:python文件执行则产生,python文件运行完毕后销毁
局部名称空间
存放的名字:在调用函数时,运行函数体代码过程中产生的函数内的名字
存活周期:在调用函数时存活,函数调用完毕后则销毁
input=333
def func():
input=444
print(input)
func()
名称空间的加载顺序
内置名称空间>全局名称空间>局部名称空间
销毁顺序
局部名称空间>全局名空间>内置名称空间
查找顺序
名字的查找优先级:当前所在的位置向上一层一层查找
内置名称空间
全局名称空间
局部名称空间
如果当前在局部名称空间:局部名称空间—>全局名称空间->内置名称空间
input=333
def func():
input=444
func()
print(input)
如果当前在全局名称空间:全局名称空间->内置名称空间
input=333
def func():
input=444
func()
print(input)
作用域
全局作用域:内置名称空间、全局名称空间
1、全局存活:python解释器启动运行代到运行结束的过程
2、全局有效:被所有函数共享
x=111
def foo():
print(x,id(x))
def bar():
print(x,id(x))
foo()
bar()
print(x)
局部作用域: 局部名称空间的名字
1、临时存活:函数调用运行代码到调用结束
2、局部有效:函数内有效
如果再局部想要修改全局的名字对应的值(不可变类型),需要用global
x=111
def func():
global x
x=222
func()
print(x)
修改全局的值(可变类型),不用global
l=[111,222]
def func():
l.append(333)
func()
print(l)
nonlocal: 修改函数外层函数包含的名字对应的值(不可变类型)
函数对象:
1、可以赋值
def func():
print("111")
f=func print(f,func) f()
2、可以当做函数参数传给另外一个函数
def func():
print("11")
f=func
print(f,func)
f()
def foo(x):
x()
foo(func)
3、可以当做函数当做另外一个函数的返回值
def func():
print("111")
f=func f()
def foo(x):
return x
res=foo(func)
print(res)
res()
4、可以当做容器类型的一个元素
l=[func,]
# print(l)
l[0]()
dic={'k1':func}
print(dic)
dic['k1']()
函数嵌套:
1、函数的嵌套调用:在调用一个函数的过程中又调用其他函数
def max2(x,y):
if x > y:
return x
else:
return y
def max4(a,b,c,d):
res1=max2(a,b)
res2=max2(res1,c)
res3=max2(res2,d)
return res3
res=max4(1,2,3,4)
print(res)
2、函数的嵌套定义:在函数内定义其他函数
def f1():
def f2():
pass