Python 函数相关知识
-
初识
函数以功能为导向,一个函数为一个功能,随调随用。
减少代码的重复性,增强代码的可读性 。
-
函数的结构以及调用
-
结构:
def mylen(s): pass return x,y
def:关键字,定义函数。
mylen:函数名,与变量设置相同规则,方便体现该函数功能。
s:传进函数的参数。
函数体:缩进,函数中尽量不要出现print。
return:
- 功能一:遇到return,则结束该函数。
- 功能二:传回返回值,给调用者。如返回多个元素,是以元组的形式返回。
-
调用:
调用时候通过“函数名():”的形式才执行函数里面的函数体。
-
-
函数的传参
-
目的:让函数封装的这个功能可以随调用者的需求而实现相应的结果。
-
参数可以分为:实参、形参
-
实参:函数执行所传进去的实际参数。
-
位置参数:从左至右,一一对应,不可多不可少,顺序不可乱。
-
关键字参数(默认参数):参数需要一一对应,不可多不可少,但是顺序可以打乱,因为调用函数时候指定参数名和值的对应进行传递。
★★★注意:默认参数如果为可变数据类型,那么不管函数调用几次,始终都是使用同一个变量。
def func(a,alist=[]): alist.append(a) return alist print(func(10)) # 第一次调用,将10追加到alist列表中 print((func(20,[]))) # 第二次调用,因为第二个参数定义了一个新的列表,所以本次调用中使用的是另一个空列表追加进了20这个数字。 print(func(100)) # 第三次调用,第二个参数没有传入,所以默认使用之前函数定义的关键字参数,这个列表里面已经有一个数字10,所以本次调用进行追加进一个数字100. >>>[10] [20] [10, 100]
-
混合参数:即传递参数时候前几个使用位置参数,后面使用关键字参数这样的形式进行传递。位置参数必须在关键字参数的前面。
-
-
形参:在函数端,接收调用者传递进来的参数(变量)。
- 位置参数:与实参角度的位置参数是一种,和实参的位置参数一一对应。
- 默认参数:经常用的参数,可以设定一个默认值。传参的时候可以省略,函数运行的时候即使用默认值。
- 万能参数: args、kwargs (*的魔性用法)
-
"args”,约定俗称:args。
-
在函数定义时,“*”代表聚合。它将所有的位置参数聚合成一个元组,赋值给了args。
-
-
“kwargs”,约定俗称:kwargs。
-
在函数定义时,“**”+变量名称(kwargs)。它将所有的关键字参数聚合成一个字典,赋值给了kwargs。
-
“*”号的魔性用法
min,*list1,max=range(10) print(min,list1,max) >>>0 [1, 2, 3, 4, 5, 6, 7, 8] 9
-
仅限关键字参数(了解):即只能是“关键字参数”。写在args和kwargs中间的关键字参数,这个参数在调用函数的时候必须要给它传递值。
-
形参的最终顺序:因为存在万能参数的原因,能够接收参数个数不定,所以形参定义的顺序必须要将位置参数放第一位,后面跟*args。
-
同理,排第三位是默认参数,后面跟kwargs。
-
最终顺序:位置参数,*args,默认参数,仅限关键字参数,**kwargs**
-
-
-
星号(*)在函数中的用法:
-
在形参角度:
1个星号+args:将所有的位置参数聚合成一个元组。
2个星号+kwargs:将所有的关键字参数聚合成一个字典。
def mysum(*args,**kwargs): n=0 for i in args: n+=i print(kwargs) return n print(mysum(4,556,1,2,12,6,7,7,453,99,name='Selina',age=18)) >>>{'name': 'Selina', 'age': 18} 1147
-
在实参(调用)角度:
1个星号+可迭代对象:将该对象打散传入函数。
def func(*args): return args print(func(*'Internet')) >>>('I', 'n', 't', 'e', 'r', 'n', 'e', 't')
2个星号+字典:将字典打散成关键字参数(name='Selina')形式传入函数。
def func(*args,**kwargs): return args,kwargs print(func(**{'name':'Selina','height':168},**{'age':18})) >>>((), {'name': 'Selina', 'height': 168, 'age': 18})
-
-
名称空间:命名空间
-
全局名称空间:里面的变量为全局变量。存放一个py文件(除去函数、类内部的)的变量,函数名与函数的内存地址的关系。
-
局部名称空间:里面的变量为局部变量。存放函数内部的变量与值的应对关系。
-
内置名称空间:为Python提供的内置函数(如:print()、len()、input()……)开辟的名称空间。
-
加载顺序:1.内置名称空间 ---> 2.全局名称空间 ---> 3.局部名称空间(执行函数的时候)
-
取值顺序:就近原则(LEGB原则),单向不可逆。
1.局部名称空间 ---> 2.全局名称空间 ---> 3.内置名称空间
name='amwkvi' def func(*args,**kwargs): # name='Selina' # 函数内部如果定义该变量,打印出来的结果将是Selina print(name) func() >>>amwkvi
-
作用域:
- 全局作用域:内置名称空间、全局名称空间。
- 局部作用域:局部名称空间。
局部作用域可以从全局作用域获取变量,换句话说,全局变量可以被函数内部引用,引用但不可修改(指不可变元素,可变元素是可以被修改的,比如列表)。反之,局部变量不可以在全局作用域中使用。
-
-
函数的嵌套(高阶函数)
-
注意函数嵌套时候的运行顺序,函数定义之后需要调用才运行,嵌套函数也是如此。
例子:
def fun2(): print(2) def fun3(): print(6) print(4) fun3() print(8) print(3) fun2() print(5) >>>3 2 4 6 8 5
-
-
globals()方法和locals()方法
-
globals()方法:返回的是全局作用域(内置+全局)中的所有内容,返回值类型为字典。
-
locals():返回的是当前作用域中的所有内容,返回值类型为字典。
a=23 b='like' def func(): name='Selina' age=18 height=168 print(locals()) # 打印输出当前作用域中的所有变量 func() print('---------------------------') print(globals()) # 打印全局作用域中的所有变量 >>>{'name': 'Selina', 'age': 18, 'height': 168} --------------------------- {'__name__': '__main__', '__doc__': ' 注释:本段代码用于研究globals()和locals()两个内置函数。 ', '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000289A90112C8>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/Python/Practice/函数/函数Practice.py', '__cached__': None, 'a': 23, 'b': 'like', 'func': <function func at 0x00000289AAC34B88>}
-
-
关键字:nonlocal、global
-
global(全局的):
-
在局部作用域内可以声明一个全局变量。
声明格式:global+空格+变量名
def func(): global name,age # 在函数内部定义了两个全局变量 name = 'amwkvi' # 定义和赋值需要分两行写 age = 18 func() print(name,age) >>>amwkvi 18
-
在函数内部可利用global关键字对某个全局变量进行修改。
name = 'amwkvi' def func(): global name # 在函数内部使用global关键字将全局变量引入到函数内部 name = name+' Walking' # 这样就可以对全局变量进行修改 return name print(name) # 调用函数之前打印name变量的值 func() print(name) # 调用函数之后再次打印,确认在函数内部可对变量进行修改。 >>>amwkvi amwkvi Walking
-
-
nonlocal(非局部的):
-
不能操作全局变量
-
函数嵌套情况下,内层函数对外层函数的局部变量进行修改。
def func(): name = 'amwkvi' def inner(): nonlocal name # 将func函数里面的name变量引入到inner函数中 name += ' Mr.H' # 现在可以对name变量进行修改,否则只能引用无法修改 print(name) # 调用inner函数之前打印name变量查看值 inner() print(name) # 调用inner函数之后查看name的值 func() >>>amwkvi amwkvi Mr.H
-
-
-
函数名的应用:
-
函数名指向的是函数的内存地址,函数名+() 就可以执行该函数。
-
即函数名就是特殊的变量。
-
类型:class 'function'
def func(): print('函数就是特殊的变量') f1 = func # 将函数名赋值给一个变量。 f2 = f1 # 再转一手。 f2() # 这个变量后面加(),可以直接执行这个函数。 print(type(f1), type(f2)) >>>函数就是特殊的变量 <class 'function'> <class 'function'>
-
函数名可以作为容器类数据类型的元素:
def func1(): # 定义三个函数 print('in func1') def func2(): print('in func2') def func3(): print('in func3') list1=[func1,func2,func3] # 函数名可以当作容器类数据的元素。 for l in list1: # 可以被遍历。 l() # 遍历出来的每个元素可以加()直接执行。
-
函数名可以作为函数的参数:
def func1(): print('in func1') def func2(f): # 位置参数f。 f() # 接收到变量之后后面加了个()。 func2(func1) # 将函数名当作位置参数传入func2中。 >>>in func1
-
函数名可以作为函数的返回值:
def func1(): print('in func1') def func2(f): print('in func2') return f # 返回值是函数名变量。 res=func2(func1) # 将函数名为作参数传入func2中。 res() # 接收到返回值之后加()就可以直接执行该函数。 >>>in func2 in func1
-
-
Python 匿名函数:lambda
匿名函数:也叫一句话函数,一行构建一个函数,比较简单的函数。
-
语法:函数名 = lambda 参数 : 返回值
1.此函数不是没有名字,他是有名字的,他的名字就是你给其设置的变量,比如func。
2.lambda 是定义匿名函数的关键字,相当于函数的def。
3.lambda 后面直接加形参,形参加多少都可以,只要用逗号隔开就行。
func = lambda a,b,*args,sex= 'alex',c,**kwargs: kwargs print(func(3, 4,c=666,name='alex')) # {'name': 'alex'} # 所有类型的形参都可以加,但是一般使用匿名函数只是加位置参数,其他的用不到。
4.返回值在冒号之后设置,返回值和正常的函数一样,可以是任意数据类型。
5.匿名函数不管多复杂,只能写一行,且逻辑结束后直接返回数据。
-
举例:
def func(a, b): return a + b # 下面构建匿名函数 func1 = lambda a, b: a + b # lambda为关键字(相当于def),冒号前面为形参,冒号后面为返回值 print(func1(3,4)) # 7
# 写匿名函数:接收一个可切片的数据,返回索引为0与2的对应的元素(元组形式)。 lam1 = lambda x: (x[0],x[2]) print(lam1('amwkvi')) # 写匿名函数:接收两个int参数,将较大的数据返回。 func1=lambda a,b: a if a>b else b print(func1(1,10))
-