博客
关于我
(四)Python总结笔记:函数
阅读量:684 次
发布时间:2019-03-17

本文共 11371 字,大约阅读时间需要 37 分钟。

Python总结笔记(四)函数

  1. python中的函数
  2. 函数中的参数
  3. 变量作用域
  4. 偏函数PFA
  5. 递归函数
  6. 高阶函数
  7. BIFs中的高阶函数
  8. 匿名函数lambda
  9. 闭包Closure
  10. 装饰器Decorator
  11. 函数式编程Functional Programming

1. python中的函数

■ 函数的意义:

■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 异常

2. 函数中的参数

■ 参数:

■语法:
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)#结论:指针(或引用)传递时,变量传递给函数的是及引用,该引用可以改变原变量

3. 变量作用域

位置与顺序

■ 标识符的作用域
globals()#全局变量名称空间
locals()#局部变量名称空间
■ 全局变量
■定义:全局变量会一直存在,除非是脚本运行结束或 del 删除它。
■经过函数时:可以被函数内部调用
■ 局部变量
■函数内部创建与访问,当被调用结束时,生命周期结束。
■ 变量的搜索顺序
■覆盖问题:重名,从局部到全局:先从局部找,找不到再去全局找。
■局部作用域->全局作用域:从局部到全局

4. 偏函数PFA

■ 偏函数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)#偏函数的类型与普通函数不一样

5. 递归函数

■ 定义:

■函数在内部调用自身
■ 例子:
■求一个列表中数值的累加

#递归的方法求一个列表中数值的累加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)

6. 高阶函数

■ 函数的引用与调用

■引用:访问,变量别名(多个别名引用)
一个对象可以被多个变量引用。
■调用:() 最后返回结果
■ 函数对象可以被引用,可以作为参数被传入或作为结果被返回。
■ 高阶函数:
一个函数接收另一个函数作为参数将函数作为变量。可接受一个指向函数变量的变量名
■ 回调函数:
■函数作为调用函数的结果返回。返回函数

#函数对象的引用 与 调用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)

7. BIFs中的高阶函数

■ 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])

8. 匿名函数lambda

■ 匿名函数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个元素升序,人口数

9. 闭包Closure

■ 闭包的概念

■涉及嵌套函数时才有闭包问题
■内层函数引用了外层函数的变量(参数),然后返回内层函数的情况,称为闭包(Closure)。
■这些外层空间中被引用的变量叫做这个函数的环境变量。
■环境变量和这个非全局函数一起构成了闭包。
■ 闭包的特点:
■函数会记住外层函数的变量
■ 闭包的实现:

10. 装饰器Decorator

■ 定义:

■以函数作参数并返回一个替换函数的可执行函数
■ 简单理解:
■装饰器的作用就是==为已存在的对象添加额外功能 ==
■为一个函数增加一个装饰(用另一个函数装饰)
■本质上就一个返回函数的高阶函数
■ 应用:
■给函数动态增加功能(函数)
■ 定义与使用:
@是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()

11. 函数式编程Functional Programming

■ 函数式编程思想:

■函数是第一等公民First Class
■函数式编程是一种编程范式,是如何编写程度的方法论。 把运算过程尽量变成一系列函数的调用。属于结构化编程
■ 特点:
■允许函数作为参数,传入另一个函数
■返回一个函数
■ 理解:
■结合本章知识点,案例进行理解

转载地址:http://ksfhz.baihongyu.com/

你可能感兴趣的文章
ms sql server 2008 sp2更新异常
查看>>
MS UC 2013-0-Prepare Tool
查看>>
MSBuild 教程(2)
查看>>
msbuild发布web应用程序
查看>>
MSB与LSB
查看>>
MSCRM调用外部JS文件
查看>>
MSCRM调用外部JS文件
查看>>
MSEdgeDriver (Chromium) 不适用于版本 >= 79.0.313 (Canary)
查看>>
MsEdgeTTS开源项目使用教程
查看>>
msf
查看>>
MSSQL数据库查询优化(一)
查看>>
MSSQL数据库迁移到Oracle(二)
查看>>
MSSQL日期格式转换函数(使用CONVERT)
查看>>
MSTP多生成树协议(第二课)
查看>>
MSTP是什么?有哪些专有名词?
查看>>
Mstsc 远程桌面链接 And 网络映射
查看>>
Myeclipse常用快捷键
查看>>
MyEclipse更改项目名web发布名字不改问题
查看>>
MyEclipse用(JDBC)连接SQL出现的问题~
查看>>
mt-datetime-picker type="date" 时间格式 bug
查看>>