本文共 11371 字,大约阅读时间需要 37 分钟。
■ 函数的意义:
■1.对输入进行变换映射后输出 ,可以进行反复调用。以函数名对代码块进行封装 ■2.过程化 VS 结构化 ■ 函数的创建及结构: ■定义函数名:def foo1(num): ■参数:num ■函数体 ■返回 □有无返回: 有返回值:return返回的是对象,(如返回对象数>1返回元组)。且返回的为最后的一个return值。 无返回值 :无返回值或者return后为空。 print可以有很多,但是return只有一个。 □return与yield的区别: print:不返回任何的函数 return 结束函数,返回值,当函数被调用时,遇到结尾或return时就准备结束了。只显示最后一个return的值。 yield:丢出一个数,对象变成了生成器–记录当前运行到哪里了。#函数的意义n=5for i in range(n): print(i) # 以函数名对以上代码块进行封装def foo(num): #函数名foo; 参数num for i in range(num): print(i)#然后进行反复调用# foo()#对输入进行变换映射后输出 #函数的定义def foo1(num):#函数名与参数#函数体 cumsum=0#函数内部的变量 for i in range(num): cumsum+=i#返回值 return cumsumfoo1(15)#函数的返回值-无返回值 def foo2():#函数名与参数#函数体 cumsum=0 for i in range(15): cumsum+=i#无返回值#或者return后为空foo2()#函数的返回值,有返回值def foo3():#函数名与参数#函数体 cumsum=0 for i in range(15): cumsum+=i #return返回的是对象,(如返回对象数>1返回元组) return cumsum,cumsum*2#函数结束foo3()#return与print在Notebook上的差异#print可以有很多,但是return只有一个# def foo2():# for i in range(5):# print(i)# foo2()# #函数的参数# def foo3(num):# for i in range(num):# print(i)# return 'Done'# foo3(1)# print(foo3(2))### 函数的返回#return与yield关键字#return 结束函数def foo1():#不返回任何的函数 print('i\'m foo1,but i return nothing')def foo2():#使用return返回值 return 'i\'m foo2, this is what i return'def foo3():#函数被调用时,遇到结尾或return时就准备结束了。 return 'i\'m foo3, this is the first return' return 'i\'m foo3, this is the secod return'#yield 丢出一个数--对象变成了生成器--记录当前运行到哪里了def foo4(): for i in range(5): return i#执行第一次时foo4函数就结束了 #yielddef foo4(): for i in range(5): yield i yield 'f' #再加入一个yield看看会不会被执行 i+=1 g1=foo4()#看一下调用foo4()返回的是什么type(g1)#看一下g1是个什么样子的对象next(g1)#继续上一次的位置,进入下一层循环#执行完最后一次循环,结束 yield语句并抛出StopIteration 异常
■ 参数:
■语法: func(positional_args,keyword_args,*tuple_nonkw_args,**dict_kw_args) positional_args位置参数 keyword_args关键字参数 tuple_nonkw_args非关键字不定长参数 dict_kw_args关键字不定长参数■ 按参数传递方式:
■位置参数(定位参数,非关键字参数) :位置顺序十分重要,不可缺少个数。对位置敏感,传递时不用指定参数名 ■关键字参数:等于号确定。intro=" " 不传关键字参数,函数依旧可以被调用,采用默认值。 传关键字参数,则覆盖默认值。 ■位置参数包裹及使用*
:一次传入不定长个位置参数。传入n个位置参数。传进来列表[] ■关键字参数包裹及使用 **
:一次性传入不定长关键字参数传入n个关键字参数。传进来字典{} 位置参数包裹可以写n个——列表;关键字参数包裹可以写n个——字典
■包裹解包顺序:首先拆位置参数包裹,按顺序给必选,默认,可变。再抓给关键字参数包裹。
■传递不定长参数时,使用包裹:位置参数 ■传递参数时,使用包裹:关键字型参数 传递不定长参数时使用包裹——位置参数必须打碎(只传递内容)再传递,传递参数同理。即:列表类型、tuple类型必须(*list);字典类型必须( * *字典)。若传(list)代表的是传对象对不上函数。l1=[1,5,6,7,2,5,3.5,9,6,3,4]mysum2(*l1)#mysum2(1,5,6,7,2,5,3.5,9,6,3,4)可以,但是mysum2(l1)不可以,因为相当于是传递了l1为一个list类型的对象。*l1表示可迭代对象,里面有多少对象就当多少对象接受。
■ 按参数的类型:
■必选(位置参数):必须写、个数要对应 ■关键字/默认:*args可变长位置参数,**kwargs可变长关键字参数 其中: *args列表 **kwargs字典 ■ 函数如何处理传入参数 ■值传递参数与指针传递参数: 值传递参数:值传递时,变量传递给函数后,函数复制一份,不会影响原有变量。 指针传递参数,会修改参数本身:指针(或引用)传递时,变量传递给函数的是及引用,该引用可以改变原变量#按参数传递方式#位置参数def foo3(companyName,websiteUrl):#位置参数的定义 print('公司名:',companyName,'公司网址:',websiteUrl)foo3('七月在线','http://www.julyedu.com')foo3('http://www.julyedu.com',websiteUrl='七月在线') #位置参数,对位置敏感,传递时不用指定参数名#关键字参数def foo4(companyName,websiteUrl,intro='专注AI教育'):#关键字参数的定义intro='专注AI教育' print('公司名:',companyName,'公司网址:',websiteUrl,'介绍:',intro)foo4('七月在线','http://www.julyedu.com')#不传关键字参数,函数依旧可以被调用,采用默认值foo4('七月在线','http://www.julyedu.com',intro='国内领先的AI教育平台')#传关键字参数,覆盖默认值#如果想一次传入不定长个位置参数,怎么办呢?#位置参数包裹及使用*def mysum1(a,b,c): return a+b+cmysum1(5,7,15)#mysum1(5,7) #报错,因为传入的参数少于函数定义时的个数#mysum1(5,7,15,22) #报错,因为传入的参数多于函数定义时的个数#这时我们就需要使用包裹*args(tuple类型)进行接收#位置参数包裹可以写n个——列表;关键字参数包裹可以写n个——字典def mysum2(*args): # print(type(args)) return sum(args)mysum2(5,7,15,22,33)#正常调用mysum2(5,7)#正常调用#那同样如果想一次性传入不定长关键字参数,也可以使用一个包裹进行接收#关键字参数包裹及使用**def filmInfo(**kwargs): print(type(kwargs)) for key,values in kwargs.items(): print(key,':',values)filmInfo(film='羞羞的铁拳',box=3.5)filmInfo(film='羞羞的铁拳',box=3.5,rate=7.9)# d1={'羞羞的铁拳':3.5,'box':3.5}#包裹解包顺序#首先拆位置参数包裹,按顺序给必选,默认,可变。#再抓给关键字参数包裹def scoreReport(name,age,*args,course='python',**kwargs): #位置;位置;位置参数包裹;关键字(默认,可以不修改);关键字参数包裹 #位置参数包裹可以写n个——列表;关键字参数包裹可以写n个——字典 print('个人信息:',name,age) for item in args: print(item) print('课程信息:',course) print('每节课成绩:') for key,value in kwargs.items(): print (key,value) scoreReport('xiaoming',22,'高中部','三年二班',Lesson1=80,Lesson2=85)scoreReport('xiaoming',22,'三年二班',course='machine learning',Lesson1=80,Lesson2=85)# #传递不定长参数时使用包裹-位置参数 必须打碎(只传递内容)再传递,即列表类型必须(*list);字典类型必须(**字典)。若(list)代表的是传对象对不上函数。l1=[1,5,6,7,2,5,3.5,9,6,3,4]mysum2(*l1)#=mysum2(1,5,6,7,2,5,3.5,9,6,3,4)# #zip案例# l1=[(1,3),(2,4)]# list(zip(*l1))# ##传递参数时使用包裹-关键字型参数# d1={'羞羞的铁拳':3.5,'雷神3':3.1,'战狼2':60}# filmInfo(**d1)
#值传递,参数本身不会被修改a=7b='julyedu'print('before reference:',a,b)def foo1(a,b): a+=1 b+='.com' print('In foo1 a,b has changed to',a,b)foo1(a,b)print('after reference:',a,b)#结论:值传递时,变量传递给函数后,函数复制一份,不会影响原有变量print('>'*40)#指针传递参数,会修改参数本身l1=[1,2,3.4]d1={ 'name':'jack'}def foo2(a,b): a.pop() b['age']=22print('before reference:',l1,d1)foo2(l1,d1)print('after reference:',l1,d1)#结论:指针(或引用)传递时,变量传递给函数的是及引用,该引用可以改变原变量
位置与顺序
■ 标识符的作用域 globals()#全局变量名称空间 locals()#局部变量名称空间 ■ 全局变量 ■定义:全局变量会一直存在,除非是脚本运行结束或 del 删除它。 ■经过函数时:可以被函数内部调用 ■ 局部变量 ■函数内部创建与访问,当被调用结束时,生命周期结束。 ■ 变量的搜索顺序 ■覆盖问题:重名,从局部到全局:先从局部找,找不到再去全局找。 ■局部作用域->全局作用域:从局部到全局■ 偏函数Partial function application
■使用场景:如果一个函数的参数很多,而在每次调用的时候有一些又经常不需要被指定时,就可以使用偏函数(近似理解为默认值)有些参数无需修改,固定部分参数 只设置了一部分的参数的函数,固定一部分参数,使得被调用时,某些参数被固定住了。 ■语法:partical(func,*args,**keywords) ■使用:from functools import partial ■原理:创建一个新函数,固定住原函数的部分参数(可以为位置参数,也可以是关键字参数),偏函数的类型与普通函数不一样,为:functools.partial。#Partial function application(PFA)# 只设置了一部分的参数的函数# 固定一部分参数,使得被调用时,某些参数被固定住了。#例如我们要定义一个函数将传进来的16进制的字符串,转换为10进制的def hex2int(num): return int(str(num),base=16)#base为关键字参数,这个在调用int这个函数时,固定给16。因为这个函数就是用来转换16进制到10进制hex2int('F')#这时调用,相当于实际上会把10作为*args的一部分自动加到左边,也就是:int('F',base=16),这样就少写了一个函数#这时也可以使用偏函数,固定int函数的关键字参数base,可以这样定义:import functoolshex2int2=functools.partial(int,base=16)#hex2int2('A')#偏函数能固定位置参数?#可以max100=functools.partial(max,100)#定义一个叫max100的偏函数,将这个偏函数的第一个值固定为100max100(101)#这时调用它,传入的值,都会与100进行比较反并返回。type(max100)#偏函数的类型与普通函数不一样
■ 定义:
■函数在内部调用自身 ■ 例子: ■求一个列表中数值的累加#递归的方法求一个列表中数值的累加def foo1(num): if len(num)==1: return num[0] else:# print(num[0],'>'*6)# print(num[1:],' >'*6) return num[0]+foo1(num[1:]) foo1([1,2,31,5,6,55])#使用递归分解质因数l1=[]def fenji(num): num=int(num) for i in range(2,num): if num%i==0: l1.append(i) nextv=int(num/i) fenji(nextv) break#这里的break不加就会硬循环60次 return l1fenji(60)#阶乘def factorial(n): if n==1: return 1 else: return n*factorial(n-1)factorial (5)
■ 函数的引用与调用
■引用:访问,变量别名(多个别名引用) 一个对象可以被多个变量引用。 ■调用:() 最后返回结果 ■ 函数对象可以被引用,可以作为参数被传入或作为结果被返回。 ■ 高阶函数: ■一个函数接收另一个函数作为参数将函数作为变量。可接受一个指向函数变量的变量名 ■ 回调函数: ■函数作为调用函数的结果返回。返回函数#函数对象的引用 与 调用num=-5a=b=c=abs#引用print(abs,a)#调用a(num)b(-8.8)c(7)#函数名本质即变量,同一个函数对象可以被多个变量引用def foo():#新建一个函数对象,并用foo这个变量名对其进行引用 passdel foo#对函数对象的引用可以删除#高阶函数def mycalucate(num,func): return func#返回函数l1=[5,8,3,6,9,15,22]mycalucate(l1,max)mycalucate(l1,min)mycalucate(l1,sum)mycalucate(l1,reversed)#回调函数def callbackfunc(*num): return maxcallbackfunc(53,5,33)
■ filter
■核心点:对每个元素做过滤 语法:filter(function,list可迭代对象) 函数 f 的作用是对每个元素进行判断,返回 True或 False。 filter()根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新list。 ■ map ■核心点:对每个元素做映射 语法:map(function, list) 让list的每一个元素依次调用function函数,并获取返回值存入一个新的list中。 ■ reduce ■核心点:两两传给func ■Python 3.x中,reduce()函数已经被从全局名字空间里移除了,它和partical一样被放置在 fucntools模块中。使用前需要调用. 语法:from functools import reduce reduce(function, list) 函数function必须包含两个参数,optional可选,如果存在则表示初值为optional reduce()对list的每个元素反复调用函数f,并返回最终结果值。l1=[2,3,5,7,3,4,5,9,'julyedu.com',[2,3,3],5,2]filter#语法:filter(function,list)# 函数 f 的作用是对每个元素进行判断,返回 True或 False# filter()根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新list。def myfilter(x): if x>60: return True else: return Falsemyfilter(61)l1=[1,61]filter(myfilter,l1)list(filter(lambda x:True if type(x)==str else False,l1))#map# 语法:map(function, list)#让list的每一个元素依次调用function函数,并获取返回值存入一个新的list中。map(lambda x:(x,l1.count(x)),l1)# reduce# 语法:reduce(function, list)#函数function必须包含两个参数,optional可选,如果存在则表示初值为optional #reduce()对list的每个元素反复调用函数f,并返回最终结果值。from functools import reducereduce(lambda a,b:a+b,[1,2,3,4,5,6,7,8])
■ 匿名函数lambda: 简化函数
■使用场景: □返回简单结束 ,不需要专门定义函数 ■特点: □简洁,同一行定义体+声明。不用写return ■定义: □定义后,赋值给一个变量,做正常函数使用 □lambda关键字定义在高阶函数的参数位上 ■语法: □lambda格式:lambda 接受n个参数:函数体,即: lambda(args1,args2, argsN):expression#匿名函数--简单的函数功能 #lambda语法:lambda 接受n个参数:函数体print(type(lambda a,b:a**b ))#定义#函数体#不用写return#使用1:作为正常函数使用,不推荐foo=lambda x,y:x+y #不用写return#lambdaprint(foo(5,6))#使用2:lambda关键字定义在高阶函数的参数位上d1={ 'china':15,'India':9,'USA':2,'Japan':1.5} #排序keysorted(d1.items(),key=lambda x:(x[0],x[1]))#按d1.items()第0个元素升序,国家名# sorted(d1.items(),key=lambda x:(x[1]))#按d1.items()第1个元素升序,人口数
■ 闭包的概念
■涉及嵌套函数时才有闭包问题 ■内层函数引用了外层函数的变量(参数),然后返回内层函数的情况,称为闭包(Closure)。 ■这些外层空间中被引用的变量叫做这个函数的环境变量。 ■环境变量和这个非全局函数一起构成了闭包。 ■ 闭包的特点: ■函数会记住外层函数的变量 ■ 闭包的实现:■ 定义:
■以函数作参数并返回一个替换函数的可执行函数 ■ 简单理解: ■装饰器的作用就是==为已存在的对象添加额外功能 == ■为一个函数增加一个装饰(用另一个函数装饰) ■本质上就一个返回函数的高阶函数 ■ 应用: ■给函数动态增加功能(函数) ■ 定义与使用: @是python装饰器的简便写法,也叫语法糖。装饰器语法糖在要被包裹的函数前声明。@后面的函数名,是包裹下边函数的函数名extrafoo。 ■ 装饰器在Python使用如此方便都要归因于 Python的函数能像普通的对象一样能作为参数传递给其他函数 可以被赋值给其他变量,可以作为返回值,可以被定义在另外一个函数内。#现有如下 三个函数def foo1(): print ('this is foo1 function')def foo2(): print ('this is foo2 function')def foo3(): print ('this is foo3 function') #现在想为每一个函数都添加一个打印当前时间的功能#一种解决办法是一个一个修改,在底部添加代码,但问题是,太麻烦了~import datetimedef foo1(): print ('this is foo1 function') print(datetime.datetime.now())def foo2(): print ('this is foo2 function') print(datetime.datetime.now()) def foo3(): print ('this is foo3 function') print(datetime.datetime.now()) #另一种办法是,写一个函数,负责打印时间,然后修改那三个函数import datetimedef printtime(): print(datetime.datetime.now()) def foo1(): print ('this is foo1 function') printtime()def foo2(): print ('this is foo2 function') printtime() def foo3(): print ('this is foo3 function') printtime()#虽然不那么麻烦了,但还是每个函数都要修改,依旧很麻烦。#法一:我们可以这样解决def foo1(): print ('this is foo1 function')def foo2(): print ('this is foo2 function')def foo3(): print ('this is foo3 function')def extrafoo(func): print(datetime.datetime.now()) return funcdecorated=extrafoo(foo2)decorated()#这样每次调用还是有点麻烦,要先写一个函数接收,再调用。OK,再弄简单一些#法二:我们可以这样解决: 已有功能foo1,现在想要加计时功能,再写一个函数,利用装饰器。import datetimedef extrafoo(func):#func代表函数对象 def inner(): print('from inner to execute:',func.__name__) print('the',func.__name__,'result:',func())#func()代表原始函数 print('extra:',datetime.datetime.now())#加计时功能,在原始函数后面加计时功能。 return inner@extrafoo#装饰器特性,被装饰的函数定义之后立即运行。@extrafoo可以理解成decorated=extrafoo(foo1)以及decorated()def foo1(): return 'this is foo1 function--'#@是python装饰器的简便写法,也叫语法糖#装饰器语法糖在要被包裹的函数前声明。@后面的函数名,是包裹下边函数的函数名extrafoo#该语法糖省略了#decorated=foo(test)#decorated()# 装饰器在Python使用如此方便都要归因于# Python的函数能像普通的对象一样能作为参数传递给其他函数# 可以被赋值给其他变量,可以作为返回值,可以被定义在另外一个函数内。foo1()
■ 函数式编程思想:
■函数是第一等公民First Class ■函数式编程是一种编程范式,是如何编写程度的方法论。 把运算过程尽量变成一系列函数的调用。属于结构化编程 ■ 特点: ■允许函数作为参数,传入另一个函数 ■返回一个函数 ■ 理解: ■结合本章知识点,案例进行理解转载地址:http://ksfhz.baihongyu.com/