Python中的函数
- 函数的意义:
- 对输入进行变换映射后输出
- 过程化VS 结构化
- 函数的创建及结构:
- 定义函数名
- 参数
- 函数体
- 返回
有无返回
(无返回值即无return或者return后为空。return返回的是对象,如返回对象数>1则返回元组)
return与yield的区别
(return:函数执行到return处返回一个对象,函数结束)
(yield:函数执行到yeild处返回一个生成器,记录函数执行情况,再次调用会接着执行)
函数中的参数
- 参数语法:func(positional_args,keyword_args,*tuple_nonkw_args,**dict_kw_args)
- 按参数传递方式:
位置参数(别称:定位参数,非关键字参数) :对位置敏感,传递时不用指定参数名
关键字参数:不传关键字参数函数可以被调用,采用默认值,传关键字参数,覆盖默认值
位置参数包裹及使用* (非关键字不定长参数 args*)
关键字参数包裹及使用**(关键字的不定长参数 kwargs*)
包裹解包顺序(首先拆位置参数包裹,按顺序给必选,默认,可变、关键字参数包裹)
传递参数时使用包裹
#位置参数包裹及使用*,一次传入不定长个位置参数
>>def mysum2(*args):
>> print(type(args))
>> return sum(args)
>>mysum2(5,7,5,8,9)#正常调用
<class 'tuple'>
34
>>def filmInfo(**kwargs):
>> print(type(kwargs))
>> for key,values in kwargs.items():
>> print(key,':',values)
#关键字参数包裹及使用**,一次性传入不定长关键字参数
>>filmInfo(film='羞羞的铁拳',box=3.5,rate=7.9)
<class 'dict'>
film : 羞羞的铁拳
box : 3.5
rate : 7.9
#传递参数时使用包裹
#传递参数时使用包裹-位置参数
>>l1=[1,5,6,7,2,5,3.5,9,6,3,4]
>>mysum2(*l1)
<class 'tuple'>
51.5
#zip案例
>>l1=[(1,3),(2,4),(5,6)]
>>list(zip(*l1)) #即 list(zip(l1[0],l1[1],l1[2]))
[(1, 2, 5), (3, 4, 6)]
##传递参数时使用包裹-关键字型参数
>>d1={'羞羞的铁拳':3.5,'雷神3':3.1,'战狼2':60}
>>filmInfo(**d1)
<class 'dict'>
羞羞的铁拳 : 3.5
雷神3 : 3.1
战狼2 : 60
- 按参数的类型:
必选(位置参数)
关键字/默认
*args可变长位置参数,**kwargs可变长关键字参数 - 函数如何处理传入参数:
值传递参数与指针传递参数
(值传递时(数值和字符串),变量传递给函数后,函数复制一份,不会影响原有变量)
(指针(或引用)传递时(列表和字典),传递给函数的是引用,该引用可以改变原变量)
变量作用域
locals()#查看局部变量名称空间
globals()#查看全局变量名称空间
- 全局变量
在模块内、在所有函数外面、在class外面
供全局共享,全局类和函数均可访问,达到同步作用。使用时,需要用global显示声明
程序执行时除非被del才会消失 - 局部变量
函数内部创建与访问
只在函数调用时存在,调用结束后变量不存在
搜索时:局部作用域->全局作用域
偏函数PFA
- 偏函数Partial function application:如果一个函数的参数很多,而在每次调用的时候有一些又经常不需要被指定时,就可以使用偏函数(近似理解为默认值)
语法:partical(func,*args,**keywords)
使用:from functools import partial
原理:创建一个新函数,固定住原函数的部分参数(可以为位置参数,或是关键字参数)
>>def hex2int1(x,base=16):
>> #base为关键字参数,在调用int函数时固定给16。用来转换16进制到10进制
>> return int(x,base)
>>hex2int('F')
#相当于:int('F',base=16),这样就少写了一个参数
#functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义
>>import functools
>>max100=functools.partial(max,100)
#定义一个叫max100的偏函数,将这个偏函数的第一个值固定为100
>>max100(101)#这时调用它,传入的值与100进行比较并返回较大的值。
101
递归函数
定义:函数在内部调用自身
#使用递归分解质因数
>>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 l1
>>fenji(60)
[2, 2, 3]
#阶乘
>>def factorial(n):
>> if n==1:
>> return 1
>> else:
>> return n*factorial(n-1)
>>factorial (5)
120
高阶函数
- 函数的引用与调用
引用:同一个对象被多个不同的变量名引用,函数对象的引用可以del删除
调用:函数名加(),使用函数
函数对象既然可以被引用,那就可以作为参数被传入或作为结果被返回 - 高阶函数: 一个函数接收另一个函数作为参数
- 回调函数: 函数作为调用函数的结果返回
#高阶函数
>>def mycalucate(num,func):
>> return func(num)
>>l1=[5,8,3,6,9,15,22]
>>mycalucate(l1,max)
>>mycalucate(l1,min)
#回调函数
def callbackfunc(*num):
return max
callbackfunc(53,5,33)
BIFs中的高阶函数
- filter
语法:filter(function,list)
使用:function函数对列表的每个元素进行判断,返回True或 False;filter()则根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新list。
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必须包含两个参数,reduce()对list的每个元素反复调用函数function,并返回最终结果值。
from functools import reduce ; reduce(lambda a,b:a+b,[1,2,3,4,5,6,7,8])
Python 3.x中,reduce()函数和partical一样被放置在fucntools模块中。使用前需要调用
匿名函数lambda
- 语法:lambda(args1,args2, argsN):expression
- 使用:
定义后,赋值给一个变量,做正常函数使用
lambda关键字定义在高阶函数的参数位上
#使用1:作为正常函数使用,不推荐
>>foo=lambda x,y:x+y #不用写return
>>print(foo(5,6))
11
#使用2:lambda关键字定义在高阶函数的参数位上
>>d1={'china':15,'India':9,'USA':2,'Japan':1.5}
# 这里sorted是高阶函数,key接受一个函数,选择排序的参照物
>>sorted(d1.items(),key=lambda x:(x[0],x[1]))
#按d1.items()第0个元素升序,国家名相同按人口数排列
# sorted(d1.items(),key=lambda x:(x[1]))#按第1个元素人口数升序排列
闭包Closure
- 定义:涉及嵌套函数时才有闭包问题,内层函数引用了外层函数的变量(参数),然后返回内层函数的情况,称为闭包(Closure)。
这些外层空间中被引用的变量叫做这个函数的环境变量。
环境变量和这个非全局函数一起构成了闭包。 - 闭包的特点:函数会记住外层函数的变量
>>nums_in_global=[15,2,3,9,3.2]#声明一个全局
>>def foo1(nums_in_function):
>> print('nums_in_function此时在是foo1中,可以被访问:',nums_in_function)
>> def foo2():
>> return max(nums_in_function)
#虽然没有给foo2传入任何参数,但foo2却能访问到foo1中的变量>>nums_in_function
# return max(nums_in_global)
#虽然没有给foo2传入任何参数,但foo2却能访问到全局变量nums_in_global
return foo2
#调用
>>foo1([5,3,8])()
nums_in_function此时在是foo1中,可以被访问: [5, 3, 8]
8
>>foo1([5,3,8])
nums_in_function此时在是foo1中,可以被 访问: [5, 3, 8]
<function __main__.foo1.<locals>.foo2>
装饰器Decorator
定义:以函数作参数并返回一个替换函数的可执行函数,为已存在的对象添加额外功能,本质上就一个返回函数的高阶函数
应用:给函数动态增加功能(函数)
使用:@是python装饰器的简便写法,也叫语法糖,语法糖在要被包裹的函数前声明。
#现有如下 三个函数
def foo1():
print ('this is foo1 function')
def foo2():
print ('this is foo2 function')
def foo3():
print ('this is foo3 function')
#现在想为每一个函数都添加一个打印当前时间的功能
#方法一:在每个函数中各添加代码打印时间,过于麻烦
#方法二:写一个函数,负责打印时间,然后在原来的三个函数中调用
#方法三:先写一个函数接收并打印时间,再调用原函数。
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 func
decorated=extrafoo(foo2)
decorated()
#方法四:使用装饰器
import datetime
def extrafoo(func):
def inner():
print('extra:',datetime.datetime.now())
print('from inner to execute:',func.__name__)
print('the',func.__name__,'result:',func())
return inner
@extrafoo#装饰器特性,被装饰的函数定义之后立即运行。
>>def foo1():
>> return 'this is foo1 function--'
>>foo1()
extra: 2018-02-08 19:38:26.047277
from inner to execute: foo1
the foo1 result: this is foo1 function--
网友评论