目录
函数基本结构:
def 函数名(形参1,形参2……):
函数体
函数的调用:函数名(实参1,实参2 ,……)
具体的例子:
>>> def mf():
for i in range(6):
print("我爱Python")
>>> mf()
我爱Python
我爱Python
我爱Python
我爱Python
我爱Python
我爱Python
>>> def mf(name,thing):
for i in range(6):
print(f"{name}爱{thing}")
>>> mf("我","中国")
我爱中国
我爱中国
我爱中国
我爱中国
我爱中国
我爱中国
>>> #可以传入多个参数
函数的参数:
1.形参和实参:
形参:函数定义时,括号内定义的参数。如:def my(name,thing),name,thing是形参。
实参:调用函数时,括号内传入的参数。如:mf("我",“中国”),“我”,“中国”是实参。
2.形参:
2.1默认参数:
例子中"苹果"就是默认参数,没有传入新的实参给q时,使用默认参数给形参q赋值。
str.join([])表示字符串的拼接。
def fun(o,p,q="苹果"):
return "".join([q,p,o])
>>> fun("吃","我")
'苹果我吃'
>>> fun("吃","我","桃子")
'桃子我吃'
>>> #没有传入实参时,使用默认参数
这个报错:SyntaxError: non-default argument follows default argument
说明默认参数要放在形参的最后面。default argument默认参数。
>>> def fun(o,p,q="苹果"):
return "".join([q,p,o])
>>> def fun(o="我",p,q="苹果"):
return "".join([q,p,o])
SyntaxError: non-default argument follows default argument
>>> #默认参数要放在形参后面
2.2位置形参:
在函数定义时,按照从左到右的顺序依次定义的形参,称之为位置形参。
def fun(o,p,q="苹果")中o,p是位置形参。每个位置形参都必须要被传值。
收集位置形参:
当用户设置函数时,每次需要的形参个数不同时,使用*args 收集位置形参。
def 函数名(*位置形参),把位置形参打包成元组。
>>> def my(*args):
print(type(args))
>>> my(1,2,3,4)
<class 'tuple'>
>>> def my():
return 1,3,4,5
>>> my()
(1, 3, 4, 5)
收集位置参数和位置参数混合使用:
由于*args表示收集任意个位置参数,所以当收集位置形参放在位置形参之前时,若实参不使用关键字参数,所有的实参都会赋值给args。
TypeError: my() missing 2 required keyword-only arguments: 'a' and 'b'
解决方法:
1.位置形参放在收集位置形参前面
2.收集位置形参放在位置形参之前时:传递实参时使用关键字实参。
>>> def my(*args,a,b):
print(*args,b,a)
>>> my(1,2,3,4)
Traceback (most recent call last):
File "<pyshell#20>", line 1, in <module>
my(1,2,3,4)
TypeError: my() missing 2 required keyword-only arguments: 'a' and 'b'
>>> #实参全部传给*args,a,b没有实参传递,我们需要设置关键字参数
>>> my(1,2,3,4,b=8,a=9)
(1, 2, 3, 4) 8 9
补充:“*”是一个匿名的收集参数。
传递值给*后面的形参时必须使用关键字实参
>>> def abc(a,*,B):
print(B,a)
>>> abc(1,B=5)
5 1
3.实参:
3.1定义参数时已经确定了位置 的参数时
3.1位置实参:
位置形参的数量与位置实参的数量必须一致,不能多传也不能少传。
实参会按照传入的位置一次赋值给形参。
"你","喜欢","我"会按照顺序传给o,p,q。
def fun(o,p,q):
return "".join([q,p,o])
>>> fun("你","喜欢","我")
'我喜欢你'
3.2关键字实参:
如果不想让实参依序传给形参,使用关键字实参。
实参中使用关键字参数,就是把实参赋给特定的形参。
>>> fun(o="你",p="喜欢",q="我")
'我喜欢你'
如果在调用函数的过程中,需要把关键字实参和位置实参混合使用:位置实参必须在关键字参数前面。否则会报错: SyntaxError: positional argument follows keyword argument
positional argument位置参数,keyword argument关键字参数
>>> fun(q="你","喜欢","我")
SyntaxError: positional argument follows keyword argument
>>> #位置参数必须在关键字参数之前
收集关键字形参:
def 函数名(**形参),传入关键字实参,把形参打包成字典。
>>> def my(**b):
print(type(b))
>>> my(a=1,c=3)
<class 'dict'>
>>> def my(**kwargs):
print(kwargs)
>>> my(a=1,b=5,m=0)
{'a': 1, 'b': 5, 'm': 0}
综合使用各个参数:
>>> def my(a,*b,**c):
print(b,a,c)
>>> my(1,4,5,6,x=0,y=9,z=8)
(4, 5, 6) 1 {'x': 0, 'y': 9, 'z': 8}
解包
收集参数(收集位置参数和收集关键字参数)使用打包的方法把参数打包输出,相对应的也有解包的方法:把字典和元组解包输出。
TypeError: my() missing 3 required positional arguments: 'b', 'c', and 'd'
报错说明未经过解包,args整个元组全部赋给a,b,c,d 三个位置参数没有值传入。
>>> args=(1,2,3,4)
>>> def my(a,b,c,d):
print(a,b,c,d)
>>> my(args)
Traceback (most recent call last):
File "<pyshell#86>", line 1, in <module>
my(args)
TypeError: my() missing 3 required positional arguments: 'b', 'c', and 'd'
>>> my(*args)
1 2 3 4
>>> kwargs={'a':1,'b':2,'c':3,'d':4}
>>> my(**kwargs)
1 2 3 4
函数的作用域:
作用域:针对一个变量可以被访问的范围
局部作用域:
变量定义在函数的内部,作用域局限于函数,其为局部变量,其作用域是局部作用域。
全局作用域:
变量定义在函数的外部,作用域不局限于函数,其为全局变量,其作用域是全局作用域。
a是局部变量,args是全局变量。
>>> args=(1,2,3,4)
>>> def my(a,b,c,d):#定义a
print(a,b,c,d)
>>> my(*args)#传递值1给形参a
1 2 3 4
>>> a#不通过函数访问a
Traceback (most recent call last):
File "<pyshell#9>", line 1, in <module>
a
NameError: name 'a' is not defined
>>> args#不通过函数访问args
(1, 2, 3, 4)
LEGB规则:
Local局部作用域
Enclosed嵌套函数的外层函数的作用域
Global全局作用域
Build-In内置作用域
设同名变量,
对嵌套内层函数A和嵌套外层函数B而言:
内层同名变量会覆盖外层函数的同名变量的值。优先级L>E
>>> def a():
x=10
def b():
x=100
print("b()",x)
>>> a()
>>> print(a())
None
>>> #只是在a()内部定义函数,没有对其进行调用
>>> def a():
x=10
def b():
x=100
print("b()",x)
b()
>>> a()
b() 100
>>> #调用b,a()中x的值被b()x的值覆盖
如果想要在嵌套内层函数中修改嵌套外层函数的同名变量的值:
使用nonlocal:
>>> def a():
x=10
def b():
x=100
print("b()",x)
b()
print(x)
>>> a()
b() 100
10
>>> #内部函数不会修改外部函数的变量
>>> def a():
x=10
def b():
nonlocal x
x=100
print("b()",x)
b()
print(x)
>>> a()
b() 100
100
对函数和全局而言:
函数同名变量会覆盖全局的同名变量的值。优先级E>G
>>> x=0
>>> print(x)
0
>>> def m():
x=1
print(x)
>>> m()
1
>>> print(x)
0
>>> #在函数中,同名的局部变量覆盖全局变量的值
如果想要在函数中修改嵌套外层函数的同名变量的值:
使用global:
>>> x=880
>>> def m():
x=55
print(x)
>>> m()
55
>>> print(x)
880
>>> #函数不会修改全局变量的值
>>> x=880
>>> def m():
global x
x=55
print(x)
>>> m()
55
>>> print(x)
55
>>> #函数修改了全局变量x的值
对全局和内置函数而言:
全局变量与内置函数的关键字相同。全局变量覆盖内置函数的值。优先级G>B
这也是变量名最好不要和关键字重名的原因。
>>> str="1234"
>>> str(45)
Traceback (most recent call last):
File "<pyshell#105>", line 1, in <module>
str(45)
TypeError: 'str' object is not callable
>>>
callable()是python的内置函数,用来检查对象是否可被调用。
在如上代码中,由于变量str和函数str重名了,所以函数在使用str函数时,发现str是一个定义好的字符串,而字符串是不能被调用的,因此抛出一个类型错误。