一、函数的基本语法
1、函数的定义:
def 函数名(参数1, 参数2, 参数3, ...): 函数体 # 函数的代码 return 返回值 # 也可以没有返回值
说明:
- 函数名只能包含字母、数字或下划线,不能以数字开头。
- 函数名可以随便取,但是要尽量短,并且要具有描述性,尽量做到“望文生义”。
- 在其他地方调用函数时,只需要通过 函数名() 的方式就可以调用。不管有没有参数,都必须有括号。
- 函数只定义了如果一直不调用,就一定不会执行。
- 函数必须先定义后使用。
二、参数
1、形参和实参
形参:形式参数,是在函数定义的时候,写在函数名后面的括号里面的参数。
实参:实际参数,是在函数调用的时候,传给函数的值;也就是在函数调用的时候,写在函数名后面括号里面的值。实参可以是常量、变量、表达式、函数等。
形参和实参的区别:
- 形参是虚拟的,不占用内存空间,只有在函数被调用时才分配内存单元。实参是一个具体的变量,占用内存空间。
- 只能把实参传给形参,不能将形参传给实参。
- 形参和实参必须一一对应。
2、形参的角度:
位置参数:必须传值,有几个参数就必须传几个值
默认参数:可以不传的参数,如果不传就使用默认的参数值,如果传了就使用传过来的参数的值。
动态参数:动态接收位置参数用*args,可以接收任意多个按位置传入的参数,接收后组织成一个元组;
动态接收关键字参数用**kwargs,可以接收任意多个按关键字传入的参数,接收后组织成一个字典。
注意顺序:位置参数,*args,默认参数,**kwargs
3、实参的角度:
按照位置传参:从左至右,一一对应的传给形参。
按照关键字传参:不用考虑参数的位置顺序,形参按照关键字来接收。
可以将位置和关键字混着传参:位置传参和关键字参数混着用。
注意顺序:必须将关键字参数放在位置参数之后,且不能给一个参数传多个值。
def my_sum(a, b): print(‘a = %s, b = %s‘%(a, b)) return a + b # 按照位置传参 print("------按位置传参------") ret = my_sum(3, 2) print(ret) # 按照关键字传参 print("------按关键字传参------") ret = my_sum(b = 2, a = 3) print(ret) # 位置和关键字混合传参 print("------混合传参------") ret = my_sum(3, b = 2) print(ret) #运行结果: ------按位置传参------ a = 3, b = 2 5 ------按关键字传参------ a = 3, b = 2 5 ------混合传参------ a = 3, b = 2 5 # 几种种错误的传参方式 ret = my_sum(3) # 错误,函数需要2个参数,实参只有一个 ret = my_sum(3, a = 2) # 错误,参数a被重复赋值了,第一个位置参数将3传给a,第二个关键字参数又将2传给了a ret = my_sum(a = 3, 2) # 错误,位置参数必须放在关键字参数的前面
4、默认参数的陷阱
如果默认参数是一个可变数据类型,每次在调用函数的时候,如果不给默认参数传值,则共用这个可变数据类型的资源
# 参数默认列表,不传值的时候,共享了这个列表;传值后就不再共享 def func(l = []): l.append(100) print(l) func() # [100] func() # [100, 100] func([]) # [100] func(l = []) # [100] func() # [100, 100, 100] # 参数默认字典,不传值的时候,共享了这个字典;传值后就不再共享 def func(k, l = {}): # l[k] = ‘v‘ # print(l) # # func(1) # {1: ‘v‘} # func(2) # {1: ‘v‘, 2: ‘v‘} # func(3,l = {}) # {3: ‘v‘} # func(4,l = {}) # {4: ‘v‘} # func(5) # {1: ‘v‘, 2: ‘v‘, 5: ‘v‘} # 但是下面这个情况不是默认参数的陷阱了。 # 因为默认参数是一个字典,字典的key不允许重新,导致后面一次调用直接修改了之前的value def func(l = {}): l[‘k‘] = ‘v‘ print(l) func() # {‘k‘: ‘v‘} func() # {‘k‘: ‘v‘} func() # {‘k‘: ‘v‘} func() # {‘k‘: ‘v‘}
5、打散和聚合
def func1(*args): print(args) # 方式一:直接按照位置将参数一个一个传入,*args返回了一个元组,这个就叫聚合 func1(1,2,3,4,5) # (1, 2, 3, 4, 5) l = [1,2,3,4,5] # 方式二、将列表l直接按照位置参数传入,*args返回了一个元组,这也是聚合,但是这个元组的元素却是一个列表,不是方式一的结果了 func1(l) # 方式三,在l前面加删个一个*传入,*args返回的结果和方式一完全一样。通过print(*l)的结果我们看到,此时不再是将列表做为参数传入了,而是将列表的元素打开一个一个传入的,这就是打散。 print(*l) func1(*l) # 运行结果: (1, 2, 3, 4, 5) ([1, 2, 3, 4, 5],) 1 2 3 4 5 (1, 2, 3, 4, 5) # =======继续**kwargs======== dic1 = {‘name‘: ‘张三‘, ‘age‘: 18} dic2 = {‘hobby‘: ‘王五‘, ‘sex‘: ‘男‘} def func(**kwargs): print(kwargs) # {‘name‘: ‘张三‘, ‘age‘: 18, ‘hobby‘: ‘王五‘, ‘sex‘: ‘男‘} func(arg1 = dic1, arg2 = dic2) # {‘arg1‘: {‘name‘: ‘张三‘, ‘age‘: 18}, ‘arg2‘: {‘hobby‘: ‘王五‘, ‘sex‘: ‘男‘}} func(**dic1, **dic2) # {‘name‘: ‘张三‘, ‘age‘: 18, ‘hobby‘: ‘王五‘, ‘sex‘: ‘男‘} #=====处理剩下的元素====== # 把1和2分别赋值给a和b a,b = (1,2) print(a, b) # 1 2 # 把1赋值给a,上下的元素聚合成一个列表赋值给b a,*b = (1, 2, 3, 4,) print(a, b) # 1 [2, 3, 4] # 最后两个元素分别赋值给a和b,前面的元素聚合成一个列表赋值给rest *rest,a,b = range(5) print(rest, a, b) # [0, 1, 2] 3 4 # 将列表打散 print([1, 2, *[3, 4, 5]]) # [1, 2, 3, 4, 5]
三、返回值
使用return关键字将函数执行的结果返回给调用它的地方,在调用它的地方用一个变量接收。当然函数也可以不用return返回值,不写return的时候,调用方接收到的是None。
说明:
- 在函数体内,遇到return函数就结束了,return下面的代码不会执行。
- 如果return后面什么都不写,或者函数体内没有return,则返回的结果是None。
- 如果return后面写了一个值,则就返回给调用者这个值。可以返回任何值。
- 如果return后面写了多个值,调用者可以对应的用多个值去接收,return返回了几个值就必须用几个变量去接收;调用者也可以使用一个值来接收这个返回值,此时这个值是一个元组。
1 def func1(): 2 return 1 3 4 def func2(): 5 return 1, 2, 3 6 7 r = func1() 8 print(‘func1 :‘, r) # func1 : 1 9 r = func2() 10 print(‘func2 :‘, r, ‘type :‘, type(r)) # func2 : (1, 2, 3) type : <class ‘tuple‘> 11 r1, r2, r3 = func2() 12 print(‘func2 :‘, r1, r2, r3) # func2 : 1 2 3
四、命名空间和作用域
1、命名空间
- 内置命名空间:python解释器已启动就可以使用的名字存在内置命名空间中。
- 全局命名空间:程序从上导下被执行的过程中一次加载进内存的变量名和函数名。
- 局部命名空间:函数内部定义的名字,只有在函数被调用的时候才会产生这个空间。函数执行完毕了,这个命名空间也就随之消失了。
- 在局部空间,可以使用全局和内置命名空间中的名字。
- 在全局空间,可以使用内置命令空间的名字,但是不能使用局部空间中的名字。
- 在内置空间,不能使用局部和全局命名空间中的名字。
- 如果我们定义了一个函数名和某个内置函数的函数名相同时,就会直接调用我们自己定义的函数,而不会再调用内置函数了
- 命名空间的加载顺序:内置命名空间(程序运行伊始加载)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程序运行中:调用时才加载)。
- 命名空间的取值顺序:取值顺序与加载顺序是相反的,取值顺序满足的就近原则,从小范围到大范围一层一层的逐步引用。
2、作用域
全局作用域:
局部作用域:
递归函数
匿名函数
内置函数
闭包
迭代器
生成器
装饰器
原文地址:https://www.cnblogs.com/Ryan-Fei/p/12103746.html
时间: 2024-10-10 10:30:50