目录

函数基本结构:

 函数的参数:

1.形参和实参:

2.形参:

3.实参:

3.1位置实参:

3.2关键字实参:

函数的作用域:

LEGB规则:


函数基本结构:

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是一个定义好的字符串,而字符串是不能被调用的,因此抛出一个类型错误。