1.函数
函数是对功能的封装
语法:def 函数名()
函数体
函数名() =--->调用函数
2.返回值
(1) 如果无函数体,不写return,没有返回值
(2) 如果在函数体中间或这末写return,返回的是None
(3) 在函数中写 return 值,返回一个值,多个返回值接受到的是元组
3.参数
函数执行的时候给函数传递信息
3.1 实参
1)位置参数
1 def chi(good_food, no_good_food, drink, ice_cream) 2 print(good_food, no_good_food, drink, ice_cream) 3 chi(‘法国鹅肝‘, ‘飞龙大辣片‘, ‘大白梨‘, ‘哈根达斯‘)
按照形参的参数位置给形参传参,当参数很多时,需要记住参数的位置
2)关键字参数
1 def chi(good_food, no_good_food, drink, ice_cream) 2 print(good_food, no_good_food, drink, ice_cream) 3 chi(drink="神仙水", ice_cream="老彬棍", good_food="盖浇饭", no_good_food="大烂片")
根据形参的参数名给形参传参
3)混合参数
前两者混合使用
1 def chi(good_food, no_good_food, drink, ice_cream) 2 print(good_food, no_good_food, drink, ice_cream) 3 chi(‘法国鹅肝‘, ‘飞龙大辣片‘, drink="神仙水", ice_cream="老彬棍")
在运用是必须先写位置参数,后写关键字参数,否则关键字参数会占位置参数的位置
(2) 形参
1) 位置参数
2) 默认参数
1 def regist(name, phone, gender=‘男‘) # 在变量声明的时候给定实参,默认值参数必须在参数列表的末尾 2 print(name,phone,gender) 3 regist(‘Shiledon‘, ‘1010011010‘) 4 regist(‘Richil‘, ‘5545‘, ‘女‘) # 不适用默认值时另给定实参
3)动态参数
*args
表示接收位置参数的动态传参,,接收到的数据类型是元组
1 def chi(*food): #函数名是food,*表示动态传参 2 print(food) 3 chi(‘可乐‘, ‘馒头‘, ‘酱油‘)
各类参数的位置:位置参数==> *args ==> 默认值参数
1 def chi(name, *food, location=‘天津‘): 2 print(name, *food, location) 3 chi(‘刘大哥‘, ‘玉米‘, ‘土豆‘)
**kwargs
关键字的动态传参:
1 def chi(**food): 2 print(food) 3 chi(good_good=‘盖浇饭‘, no_good_food=‘卫龙‘, drink=‘可口可乐‘)
顺序:位置参数==> *args ==> 默认值参数 ==> **kwargs
文档注释也可以称为函数注释:
1 def func(a, b): 2 """ 3 这一行用来解释这个函数的功能 4 :param a: 第一个参数值 5 :param b:第二个参数值 6 :return:返回值 7 """ 8 return a+b 9 10 print(func(1, 4)) 11 print(func.__doc__) 12 print(str.__doc__) #可以看其他类型数据的文档注释
1 def func(*food): #这里是将所有的food参数聚合到一个元组中 2 print(food) 3 lst = [‘煎饼果子‘, ‘来一套‘, ‘美滋滋‘] 4 func(*lst) # 这个时候是将传参列表中的元素打散,方便传参,可以打散list,tuple,dic,set
1 def func(**food): 2 print(food) 3 dic = {"good_food":"煎饼果子", "no_good_food":"辣条"} 4 func(**dic) #字典打散成关键字参数
1.函数名也可以当作变量名进行使用
1 def func_1(): 2 print(‘我是1‘) 3 def func_2(): 4 print(‘我是2‘) 5 6 def func_3(): 7 print(‘我是3‘) 8 9 lst = [func_1, func_2, func_3] 10 for el in lst: 11 el()
2.函数名可以作为参数传递给函数
1 def my(): 2 print(‘我是my‘) 3 def proxy(fn): # proxy代理 4 print(‘在处理之前‘) 5 fn() 6 print(‘在处理之后‘) 7 8 proxy(my) 9 10 # 结果:在处理之前 11 # 我是my 12 # 在处理之后
3.函数可以作为返回值
1 def func(): 2 print(‘我是func‘) 3 a = 10 4 def inner(): 5 print(‘我是inner‘) 6 return inner # 返回函数inner的内存地址 7 print(func())
如果要执行inner():
1 def func(): 2 print(‘我是func‘) 3 a = 10 4 def inner(): 5 print(‘我是inner‘) 6 return inner # 返回函数inner的内存地址 7 ret = func() 8 ret()
在python解释器开始执行之后, 就会在内存中开辟一个空间, 每当遇到一个变量的时候, 就把变量名和值之间的关系记录下来, 但是当遇到函数定义的时候, 解释器只是把函数名读入内存, 表示这个函数存在了, 至于函数内部的变量和逻辑, 解释器是不关心的. 也就是说一开始的时候函数只是加载进来, 仅此而已, 只有当函数被调用和访问的时候, 解释器才会根据函数内部声明的变量来进行开辟变量的内部空间. 随着函数执行完毕, 这些函数内部变量占用的空间也会随着函数执行完毕而被清空。
命名空间分类:
? 1. 全局名称空间—> 我们直接在py文件中, 函数外声明的变量都属于全局名称空间
? 2. 局部名称空间—> 在函数中声明的变量会放在局部名称空间
? 3. 内置名称空间—> 存放python解释器为我们提供的名字, list, tuple, str, int这些都是内置名称空间
1 全局名称空间 2 a = 10 # 全局名称空间中的内容 3 def func(): # func()也在全局名称空间中 ==> 顶格 4 b = 10 # b为局部变量 5 return a*b 6 def func_1(): 7 print(a) 8 print(func()) 9 func_1() 10 python的命名空间:内置变量==> 全局变量 ==> 局部变量(函数调用的时候产生)
1 a = 10 2 def fn(): 3 b = 20 4 def gn(): 5 pass 6 print(globals()) 7 print(locals()) 8 gn() # 局部的函数要在内部进行调用 9 fn()
global
1 a = 10 2 def fn(): 3 global a # global可以将全局中的内容引入到函数内部 4 a = 20 5 fn() 6 print(a)
1 a = 10 2 def fn(): 3 global a # global可以将全局中的内容引入到函数内部 4 5 a += 10 # 此时局部没有变量a,会将全局的a引入到局部,先进行a+10然后赋值 6 # 给a,但是a是全局变量,不能修改,所以程序不能执行,所以应该加入global 7 fn() 8 print(a)
nonlocal
1 def outer(): 2 a = 10 3 def inner(): 4 nonlocal a # 寻找外层函数离它最近的变量 5 a = 20 6 inner() 7 print(a) 8 outer()
闭包:在内层函数中访问外层函数的变量
1 def outer(): 2 a = 10 3 def inner(): 4 print(a) 5 inner() 6 outer()
闭包的作用:
1.可以保护变量不受侵害
1 def outer(): 2 a = 10 # 函数内部的变量a对于外界是不开放的 3 def inner(): 4 nonlocal a 5 a = 20 6 print(a) 7 inner()
2.可以让一个变量常驻内存
1 def outer(): 2 a = 10 # 常驻内存,为了inner执行的时候有值 3 def inner(): 4 print(a) 5 return inner 6 fn = outer() 7 fn()
可以用closure查看是否闭包:
1 def func(): 2 a = 10 3 def inner(): 4 print(a) 5 print(inner.__closure__) # 如果打印的是None,则不是闭包 6 7 func()
原文:https://www.cnblogs.com/Studying-Du/p/12349890.html