1. 函数的意义和定义
# 函数的作用:python中的函数可以像变量一样,动态创建,销毁,当参数传递,作为值返回,叫第一类对象.其他语言功能有限 1.函数名是个特殊的变量,可以当做变量赋值 2.函数名可以作为容器类型数据的元素 3.函数名可以作为函数的参数 4.函数名可作为函数的返回值 __doc__或者help查看文档
# 函数概念: 满足某一个方法 满足某一个功能 # (1) 功能:包裹一部分代码 实现某一个功能 达成某一个目的 # (2) 可以反复调用,提高代码的复用性,提高开发效率,便于维护管理 # (3) 函数的基本格式: ''' # 定义一个函数 def 函数名(): code # 调用函数 函数名() ''' # 函数的定义处 def func(): print("天下武功为快不破") # 函数的调用处 func()
2. 函数的命名
函数的命名
字母数字下划线 首字符不能为数字
严格区分大小写 且不能使用关键字
函数命名有意义 且不能使用中文哦
驼峰命名法:
(1)大驼峰命名法 : myfunc => MyFunc 应用在面向对象程序当中的类名
(2)小驼峰命名法 :myfunc => myFunc 用在函数上(不做强制要求)
myfunc => my_func (推荐)
3. 函数的参数
(1) 普通形参、默认形参、普通实参、关键字实参
''' 参数分类: 形参 和 实参 形参: 形式参数 在函数的定义处 实参: 实际参数 在函数的调用处 形参包含: 普通形参, 默认形参, 普通收集形参, 命名关键字形参, 关键字收集形参 实参包含: 普通实参,关键字实参 形参 和 实参 要一一对应 ''' # row,a,b 是普通形参,在传参数的时候,要按顺序传参 def LittleStar(row, a, b, col=80): i = 0 while i < row: j = 0 while j < col: print ("*", end='') j += 1 print() i += 1 LittleStar(5, 0, 0) #使用了 col=80 的默认值,即使用默认形参 LittleStar(5, 0, 0, 110) # 使用了 col=100 实际参数,即使用普通实参 LittleStar(5, b=3, col=10, a=100) # 使用了关键字实参进行调用,顺序随意
(2)收集参数(普通收集参数、关键字收集参数)
''' (1) 普通收集参数 (可变参数) 语法: def func(*参数名): pass 参数前面加上一个 * 的就是普通收集参数; 普通收集参数专门用于收集多余的普通实参,形成一个元组 arg => argument 参数 ''' def func(a, b, c, *arg): print(a, b, c, end='\t\t') # 1, 2, 3 print('arg: ', arg) # (4, 5, 6) func(1, 2, 3, 4, 5, 6) ''' (2) 关键字收集参数 # 语法 def func(**参数): pass 参数前面加上**的就是关键字收集参数 关键字收集参数:用于收集多余的关键字实参,形成一个字典 def func(a, b, c, **kwargs): pass # kwargs => keyword arguments ''' def func(a, b, c, **kwargs): print(a, b, c, end='\t\t') print('kwargs: ', kwargs) func(1, 2, 3, f=11, d=13, zz=99)
执行结果:
1 2 3 arg: (4, 5, 6) 1 2 3 kwargs: {'f': 11, 'd': 13, 'zz': 99}
(3) 命名关键字
''' # 命名关键字 # 语法: def func(参数1, 参数2, *, 参数3, 参数4): pass (1) 在函数的定义处, * 号后面的参数就是命名关键字参数 (2) 在函数的定义处, 在普通收集参数和关键字收集参数之间的是命名关键字参数 def func(*arg, 命名关键字参数, **kwargs) 命名关键字必须使用关键字实参的形式进行调用 ''' # 形式1 def func(a, b, *, c): print(a, b, c) func(1, 2, c=4) # 必须写上*号后面的参数名并赋值 c=4 # 形式2 ''' 如果命名关键字指定了默认值,那么在调用时, 可以不指定实参.默认使用自己的值 ''' def func(a, b, *, c=5): print(a, b, c) func(1, 2, c=6) # c为命名关键字默认参数,可以不传,但传参时,必须写上 c=4 # 形式3 def func(*arg, d, **kwargs): print(arg) # 1 2 23 print(kwargs) # {c:1,f:2} print(d) # d = 3 func(1, 2, 23, c=1, f=2, d=3) # d为命名关键字,必须写上 d=xxx
4. 函数的返回值
# 函数的返回值 return return: 自定义返回值 , 返回到哪里? 返回到函数的[调用处] return 后面可以跟上六大标准数据类型 , 除此之外,可以跟上 类对象,函数,如果不写return ,默认返回None return 如果执行了return ,意味着 return后面得所有代码,统统不执行,函数终止了.
5. 变量相关(global / locals / globals / nonlocal)
# 作用域:作用范围 # 命名空间 : 划分一块区域保存所有数据,以字典的方式存储(变量与值形成映射关系).一共三种. (1)内建命名空间:解释器启动时创建,直到解释器运行结束,生存周期最长 (2)全局命名空间:文件运行时创建,直到解释器运行结束,生存周期较长 (3)局部命名空间:函数调用时,里面的局部变量才创建,调用结束后即释放,生存周期较短 #命名空间的提出是为了划分和控制变量是否可见,以及生存周期的长短. #命名空间 创建顺序:(了解) python解释器启动->创建内建命名空间->创建全局命名空间->创建局部命名空间 #命名空间 销毁顺序:(了解) 函数调用结束后->销毁函数对应的局部命名空间数据->销毁全局命名空间数据->销毁内建命名空间数据
global :关键字:声明全局变量获修改全局变量 locals() :返回字典,当前作用域所有内容(locals调用之前的变量) globals() :返回字典,存放着全局作用域所有内容 nonlocal :关键字:修改局部变量(当前函数上一层的局部变量)
(1)global 全局变量的获取和定义
了解 global 之前,先了解一下局部变量和全局变量: 局部变量:在函数内部声明的变量就是局部变量. 全局变量:在函数外部声明的变量或用global关键字在函数内部声明的变量 作用域:作用的范围 局部变量:作用范围在函数的内部 全局变量:作用范围横跨整个文件 ''' python特有: 如果外部存在该全局变量,那么利用global关键字,可以允许在函数内部修改全局变量 如果外部不存在该全局变量,那么利用global关键字,可以允许在函数内部定义全局变量 在使用global 关键字的时候,一般写在函数内部的第一行. '''
c = 78 def func1(): a = 1 # 为局部变量 # 如果不加 global c 只能获取 不能修改 # 加了global c 告诉系统在函数内部允许修改全局变量c global c print(c) c = 90 def func2(): global a # 在函数内部通过global 定义全局变量 a = 985
(2)locals
locals 获取当前作用域的所有变量
''' locals 获取当前作用域的所有变量 ''' # 获取打印返回值之前的所有内容 a = 10 b = 20 res = locals() c = res['__name__'] print('c: ', c) print('res: ', res) d = 30 # 获取调用 locals 之前的所有的内容 def func(): f1 = 11 f2 = 12 res = locals() f3 = 13 print('func var: ', res) func()
执行结果:
c: __main__ res: {'__name__': '__main__', '__doc__': '\nlocals 获取当前作用域的所有变量\n', '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001B002DE4390>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:\\test.py', '__cached__': None, 'a': 10, 'b': 20, 'res': {...}, 'c': '__main__'} func var: {'f1': 11, 'f2': 12}
(3)globals
''' globals 只获取全局变量(无论在函数内外都只获取全局变量) globals 返回的是系统的 全局命名空间的字典 ,在空间里面放的全局变量 ''' # (1) 如果在函数的外面,获取globals()返回值打印之前, 所有的内容. a = 5 res = globals() b = 15 print('函数外部: ', res) # 拿不到 c 以及之后的元素 c = 26 # (2) globals 如果在函数的里面,获取globals调用之前,所有的内容 # (3) globals 动态创建全局变量 def func(): f1 = 1 # globals 如果在函数的里面,获取globals调用之前,所有的内容 res = globals() f2 = 2 print('函数内部: ', res) # globals 可以批量创建全局变量 for i in range(3): res["a%d" % (i)] = i func() print('a0: ', a0) print('a1: ', a1) print('a2: ', a2) d = 10
执行结果:
函数外部: {'__name__': '__main__', '__doc__': '\nglobals 只获取全局变量(无论在函数内外都只获取全局变量)\n', '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000017D3B5C4390>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:\\test.py', '__cached__': None, 'a': 5, 'res': {...}, 'b': 15} 函数内部: {'__name__': '__main__', '__doc__': '\nglobals 只获取全局变量(无论在函数内外都只获取全局变量)\n', '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000017D3B5C4390>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:\\test.py', '__cached__': None, 'a': 5, 'res': {...}, 'b': 15, 'c': 26, 'func': <function func at 0x0000017D3B57C1E0>} a0: 0 a1: 1 a2: 2
(4)nonlocal (符合LEGB原则)
#找寻变量的调用顺序采用 LEGB 原则(即就近原则) B —— Builtin(Python);Python内置模块的命名空间 (内建作用域) G —— Global(module); 函数外部所在的命名空间 (全局作用域) E —— Enclosing function locals;外部嵌套函数的作用域 (嵌套作用域) L —— Local(function);当前函数内的作用域 (局部作用域) 依据就近原则,从下往上,从里向外,依次寻找
演示代码:
# nonlocal 修改的是局部变量,不是全局变量. a = 10 def outer(): a = 100 def inner(): a = 1000 def smaller(): nonlocal a # 修改外层第一个局部变量 a += 1 # 不可修改,仅可修改容器类型参数 smaller() print(a) inner() print(a) outer() print(a)
执行结果:
1001 100 10
6.闭包函数
闭包的定义:
内函数使用外函数的局部变量,并且外函数将内函数返回出来的方法叫闭包,
返回的内函数叫闭包函数。
闭包的特点:
内函数使用了外函数的局部变量,外函数的局部变量与内函数发生绑定,延长该变量的生命周期 (实际内存给它存储了这个值,暂时不释放)
闭包的意义:
闭包可以优先使用外函数中的变量,并对闭包中的值起到了封装保护的作用。外部无法访问。
演示代码:
def outer(): a = 5 # inner 是闭包函数 def inner(): print(a) return inner # outer()() res = outer() # res = inner res() # res() = inner()
7.匿名函数
匿名函数,顾名思义就是没有名字的函数。 特点:使用 lambda 定义,而不是使用 def 定义;不用写 return 关键字。 结构:lambda 参数: 返回值
演示代码:
# 定义 fun = lambda arg: "执行我啦" # 调用,与普通函数一样 fun() # 一行实现函数的定义调用和输出 print((lambda x, y: x * 10 + y)(96, 1)) # 961 # 三目运算 print((lambda n: True if n > 8 else False)(10)) # False