一、函数定义方法:
def fuc_name(value): #fuc_name函数名,value为参数可以为多个,也可以没有参数 "the function definition" #函数描述 value+=1 #代码块 return value
#定义返回值:
若返回值=0,返回None
若返回值=1,返回object
若返回值>1,返回tuple
若
def test01(): msg = 'test01' print(msg) def test02(): msg = 'test02' print(msg) return msg def test03(): msg = 'test03' print(msg) return 1,2,3,4,'a',['alex'],{'name':'alex'},None def test04(): msg = 'test03' print(msg) return {'name':'alex'} t1=test01() t2=test02() t3=test03() t4=test04() print(t1) print(t2) print(t3) print(t4)
如果函数的返回值是一个函数名,则返回函数地址
def test1(): print('in the test1') def test(): print('in the test') return test1 # print(test) res = test() print(res) print(res()) # test1() ''' result: in the test <function test1 at 0x008D92B0> in the test1 '''
如果函数的返回值是一个func(),则运行完func后,再返回func的return
def bar(): print('from bar') def foo(): print('from foo') return bar() n = foo() print(n) ''' result: from foo from bar None '''
二、参数
1、形参只有在调用的时候才占内存
2、位置参数和关键字参数:
位置参数必须一一对应,缺一不行,多一也不行
关键字参数不必一一对应,缺一不行,多一也不行
混合使用时,关键字参数在位置参数右边
3、默认参数
def handle(x,type='mysql'): print(x) print(type) handle('hello') handle('hello',type='sqlite') handle('hello','sqlite')
4、参数组 :**字典 *列表
①*args
def test(x,*args): print(x) print(args) test(1) #args=() test(1,2,3,4,5) #args=(2,3,4,5) test(1,{'name':'alex'}) #args=({'name': 'alex'},) test(1,['x','y','z']) #args=(['x', 'y', 'z'],),以一个整体传入 test(1,*['x','y','z']) #args=('x', 'y', 'z'),按遍历方式传入 test(1,*('x','y','z')) #args=('x', 'y', 'z')
②**kwargs
def test(x,**kwargs): print(x) print(kwargs) test(1,y=2,z=3) #kwargs={'y': 2, 'z': 3} test(1,1,2,2,2,2,2,y=2,z=3)#会报错 test(1,y=2,z=3,z=3)#会报错 :一个参数不能传两个值
③*args,**kwargs
def test(x, *args, **kwargs): print(x) print(args, args[-1]) print(kwargs, kwargs.get('y')) test(1,1,2,1,1,11,1,x=1,y=2,z=3) #报错,由于x赋值两次 test(1, 1, 2, 1, 1, 11, 1, y=2, z=3) ''' args=(1, 2, 1, 1, 11, 1) args[-1]=1 kwargs={'y': 2, 'z': 3} kwargs.get('y')=2 ''' test(1, *[1, 2, 3], **{'y': 1}) ''' args=(1, 2, 3) args[-1]=3 kwargs={'y': 1} kwargs.get('y')=1 '''
三、局部变量与全局变量
全局变量变量名大写
局部变量变量名小写
局部作用域里的变量定义不影响作用域外,
如果函数中无global,调用时先在当前作用域中找,只能读取全局变量,不能重新赋值,
但对于可变类型,可对内部元素进行操作
name = "we" def ex(): name = 123 print(name) ex() # 123 print(name) # we
NAME = ["产品经理", "廖波湿"] def qupengfei(): global NAME NAME.append('XXOO') print('我要搞', NAME) qupengfei()
函数内定义的变量外部不能调用:
name = "we" def ex(): name1 = 123 print(name1) ex() # 123 print(name1) # 报错
未调用函数之前,函数定义内的代码块不编译:
NAME = "杠娘" def yangjian(): # NAME = "史正文" global NAME NAME = "小东北" print('我要搞', NAME) def qupengfei(): # NAME = "基" print('我要搞', NAME) qupengfei() yangjian() qupengfei() ''' 打印结果为: 我要搞 杠娘 我要搞 小东北 我要搞 小东北 '''
如果要在函数中更改全局变量要使用global,变量本质上就是全局那个变量,可读取和赋值,global放在局部变量前
name = "we" def ex(): global name name = 123 print(name) ex() # 123 print(name) # 123
四、函数的嵌套&调用与相对全局/局部变量
函数执行顺序
NAME = '海风' # 第1步 def huangwei(): # 第2步:将函数体写入内存,但不执行 name = "黄伟" # 第4步 print(name) # 第5步 def liuyang(): # 第6步:将函数体写入内存,但不执行 name = "刘洋" # 第8步 print(name) # 第9步 def nulige(): # 第10步:将函数体写入内存,但不执行 name = '沪指花' # 第13步 print(name) # 第14步 print(name) # 第11步 nulige() # 第12步 liuyang() # 第7步 print(name) # 第15步 huangwei() # 第3步 ''' 运行结果: 黄伟 刘洋 刘洋 沪指花 黄伟 '''
无论嵌套几层,global永远代指最外层的绝对全局变量:
name = "刚娘" def weihou(): name = "陈卓" def weiweihou(): global name name = "冷静" weiweihou() print(name) print(name) weihou() print(name) ''' 执行结果: 刚娘 陈卓 冷静 '''
nonlocal,指定上一级变量,如果没有就继续往上直到找到为止:
name = "刚娘" def weihou(): name = "陈卓" def weiweihou(): nonlocal name # nonlocal,指定上一级变量,如果没有就继续往上直到找到为止 name = "冷静" print(name) weiweihou() print(name) print(name) weihou() print(name) ''' result: 刚娘 陈卓 冷静 刚娘 '''
五、调用函数的向前引用:
函数==变量
1、调用函数前必须先定义函数
2、代码从上到下阅读,读到就将内容写入内存
正确示例:
def bar(): print('from bar') def foo(): print('from foo') bar() foo()
def foo(): print('from foo') bar() def bar(): print('from bar') foo()
错误示例:
def foo(): print('from foo') bar() foo()
def foo(): print('from foo') bar() foo() def bar(): print('from bar')
六、递归
1、必须有一个明确结束条件
2、每进入一次递归,问题规模应比上一次减小
3、递归效率不高,递归层数过多导致栈的溢出
递归问路(可断点理清思路)
person_list = ['alex', 'wupeiqi', 'linhaifeng', 'zsc'] def ask_way(person_list): print('-' * 60) if len(person_list) == 0: return '根本没人知道' person = person_list.pop(0) if person == 'linhaifeng': return '%s说:我知道,老男孩就在沙河汇德商厦,下地铁就是' % person print('hi 美男[%s],敢问路在何方' % person) print('%s回答道:我不知道,但念你慧眼识猪,你等着,我帮你问问%s...' % (person, person_list)) res = ask_way(person_list) print('%s问的结果是: %s' % (person, res)) return res res = ask_way(person_list) print(res)
NAME = '海风' # 第1步 def huangwei(): # 第2步:将函数体写入内存,但不执行 name = "黄伟" # 第4步 print(name) # 第5步 def liuyang(): # 第6步:将函数体写入内存,但不执行 name = "刘洋" # 第8步 print(name) # 第9步 def nulige(): # 第10步:将函数体写入内存,但不执行 name = '沪指花' # 第13步 print(name) # 第14步 print(name) # 第11步 nulige() # 第12步 liuyang() # 第7步 print(name) # 第15步 huangwei() # 第3步 ''' 运行结果: 黄伟 刘洋 刘洋 沪指花 黄伟 '''
七、函数的作用域
函数的作用域只跟函数声明时定义的作用域有关,跟函数的调用位置无任何关系
注意:
foo()()()的运行与结果
name = 'alex' def foo(): name = 'lhf' def bar(): name = 'wupeiqi' print(name, 'in bar', sep=':') def tt(): print(name, 'in tt', sep=':') return tt return bar r1 = foo() r2 = r1() # tt r3 = r2() foo()()() ''' result: wupeiqi:in bar wupeiqi:in tt wupeiqi:in bar wupeiqi:in tt '''
八、匿名函数
形式:
lamda 形参:返回值
直接打印匿名函数,返回值是函数地址
print(lambda x: x + 1) ''' result: <function <lambda> at 0x005D9268> '''
单独调用匿名函数需要给匿名函数命名
func = lambda x: x + 1 print(func(10)) ''' result: 11 '''
返回多个值时要加括号(元组)
lambda x,y,z:(x+1,y+1,z+1) #正常运行 lambda x,y,z:x+1,y+1,z+1 #报错 ''' 正常函数定义时,return值系统直接转换成元组 ''' def test(x,y,z): return x+1,y+1 #----->(x+1,y+1)
九、函数式编程
更多内容见:egon09.blog.51cto.com/9161406/1842475
1、高阶函数:
1、函数接收的参数是一个函数名
或
2、返回值中包含函数名
# 函数接收的参数是一个函数名 def foo(n): # n=bar print(n) def bar(name): print('my name is %s' % name) foo(bar('alex'))
# 返回值中包含函数 def bar(): print('from bar') def foo(): print('from foo') return bar n = foo() n()
2、map函数
num_l = [1, 2, 10, 5, 3, 7] # map示例 res = map(lambda x: x + 1, num_l) print('内置函数map,处理结果', res) ''' result: 内置函数map,处理结果 <map object at 0x0055C190> ''' for i in res: print(i) ''' result: 2 3 11 6 4 8 ''' print(list(res)) ''' 由于前面 for i in res: print(i) 所以这里的result: [] 如果没有 for i in res: print(i) result: [2, 3, 11, 6, 4, 8] ''' # 对map函数的理解 def reduce_one(x): return x - 1 def map_test(func, array): # func=lambda x:x+1 arrary=[1,2,10,5,3,7] ret = [] for i in array: res = func(i) # add_one(i) ret.append(res) return ret print(map_test(lambda x: x + 1, num_l)) ''' result: [2, 3, 11, 6, 4, 8] ''' print('传的是有名函数', list(map(reduce_one, num_l))) ''' result: 传的是有名函数 [0, 1, 9, 4, 2, 6] ''' msg = 'linhaifeng' print(list(map(lambda x: x.upper(), msg))) ''' result: ['L', 'I', 'N', 'H', 'A', 'I', 'F', 'E', 'N', 'G'] '''
3、filter函数
# filter函数 movie_people = ['alex_sb', 'wupeiqi_sb', 'linhaifeng', 'yuanhao_sb'] print(filter(lambda n: not n.endswith('sb'), movie_people)) # --><filter object at 0x00502FD0> res = filter(lambda n: not n.endswith('sb'), movie_people) print(list(res)) # -->['linhaifeng'] print(list(filter(lambda n: not n.endswith('sb'), movie_people))) # -->['linhaifeng']
对filter函数的理解
movie_people = ['alex_sb', 'wupeiqi_sb', 'linhaifeng', 'yuanhao_sb'] def filter_test(func, array): ret = [] for p in array: if not func(p): ret.append(p) return ret res = filter_test(lambda n: n.endswith('sb'), movie_people) print(res) # -->['linhaifeng']
4、reduce函数
python 3中调用reduce函数需要
from functools import reduce
from functools import reduce num_l = [1, 2, 3, 100] print(reduce(lambda x, y: x + y, num_l, 1)) # -->107 print(reduce(lambda x, y: x + y, num_l)) # -->106
对reduce函数的理解
num_l = [1, 2, 3, 100] def reduce_test(func, array, init=None): if init is None: res = array.pop(0) else: res = init for num in array: res = func(res, num) return res print(reduce_test(lambda x, y: x + y, num_l, 1)) # -->107
5、总结
map()处理序列中的每个元素,得到的结果是一个‘列表’,该‘列表’元素个数及位置与原来一样
filter遍历序列中的每个元素,判断每个元素得到布尔值,如果是True则留下来
reduce:处理一个序列,然后把序列进行合并操作
#filter() people=[ {'name':'alex','age':1000}, {'name':'wupei','age':10000}, {'name':'yuanhao','age':9000}, {'name':'linhaifeng','age':18}, ] print(list(filter(lambda p:p['age']<=18,people)))
#reduce from functools import reduce print(reduce(lambda x,y:x+y,range(100),100)) print(reduce(lambda x,y:x+y,range(1,101)))
十、内置函数
详见https://docs.python.org/3/library/functions.html?highlight=built#ascii