1.高阶函数(map/reduce/filter)

高阶函数是指函数的参数可以是函数

这篇总结几个常用的高阶函数:map/reduce/filter

map函数、reduce函数、filter函数都是Python中的内建函数。

map函数

map函数的作用是将一个函数作用于一个序列的每一个元素,一行代码即可完成,不需要用我们平常喜欢用的循环。map将运算进行了抽象,我们能一眼就看出这个函数是对一个序列的每个元素进行了同样的一个操作。map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。

注意第一个参数只需要传函数名,而这个函数参数就是后面的序列的每一个元素传入。由于map的结果是一个Iterator,Iterator是惰性序列,因此通过list()函数让它把整个序列都计算出来并返回一个list。

def mul(x):
return x*x r = list(map(mul, [1,2,3,4,5,6,7,8,9]))
#或简化:
r = list(map(lambda x:x*x, [1,2,3,4,5,6,7,8,9]))

reduce函数

reduce也是把一个函数作用在一个序列上,它必须接收两个参数,把前两个参数计算的结果作为第一个参数继续和序列的下一个元素进行累积计算,即:

reduce(f, [x1, x2, x3, x4,x5]) = f(f(f(f(x1, x2), x3), x4),x5)

例1:

#将list转化成一个整数
from functools import reduce
L=[1,2,5,8]
print(reduce(lambda x,y: x*10+y, L))#1258

注意:

reduce()要从functools中import

lambda函数是匿名函数,我们可以用lambda函数进行一些简单进行,省去定义函数。lambda函数的参数可以0个或多个,参数用逗号分隔。参数后跟冒号,再跟表达式,返回的是计算的结果。

例2:

#将字符串转化成整数
from functools import reduce
def str2int(s):
def str2num(x):
DIGITS={'': 0, '': 1, '': 2, '': 3, '': 4, '': 5, '': 6, '': 7, '': 8, '': 9}
return DIGITS[x]
return reduce(lambda y,z:y*10+z, map(str2num,s))
print('')#9748
#将字符串转化成浮点数
from functools import reduce
def str2float(s):
DIGITS = {'': 0, '': 1, '': 2, '': 3, '': 4, '': 5, '': 6, '': 7, '': 8, '': 9}
def str2num(a):
return DIGITS[a]
return reduce(lambda x,y:x*10+y, map(str2num, s.split('.')[0])) +reduce(lambda x,y:x*10+y, map(str2num, s.split('.')[1]))*10**(-len(s.split('.')[1]))

filter函数

filter函数和map函数类似,接收两个参数,一个是函数,第二个是一个序列。filter函数把传入的函数依次作用于序列的每一个元素,根据函数的返回值是True还是False决定保留或删除该元素。

如我们想找出一个序列中的所有偶数,等等。

#删除序列中元素的所有空格
def not_empty(s):
return s and s.strip() list(filter(not_empty, ['A', '', 'B', None, 'C', ' ']))
# 结果: ['A', 'B', 'C']
#返回一个范围内的所有回数(从左至右和从右至左,是同一个数字)
def is_palindrome(n):
s=str(n)
return s[::1] == s[::-1] # 测试:
output = filter(is_palindrome, range(1, 200))
print(list(output))
#结果:[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99, 101, 111, 121, 131, 141, 151, 161, 171, 181, 191]

2.函数嵌套

函数嵌套分为函数嵌套定义和函数嵌套调用。

函数嵌套定义即在一个函数定义的函数体内定义另外一个函数:

#函数嵌套定义示例
def f():
print("f")
def f1():
print("f1")
def f2():
print("f2")
f2()
f1() f()
#结果:f
# f1
# f2

还可以将嵌套定义的函数作为return的参数(这种用法在下面的闭包中详细介讲解),下面的代码跟上面的代码输出结果一致。

def f():
print("f")
def f1():
print("f1")
def f2():
print("f2")
return f2
return f1 t1 = f()#t1就是f1
t2 = t1()#即调用f1(),t2就是f2
t3 = t2()#即调用f2()

函数嵌套调用就是在一个函数体里面调用另外一个函数。

例:在func2中调用了func1函数

#函数嵌套调用示例
def func1(x,y):
return x*y def func2(a,b,c):
r1 = func1(a,b)
r2 = func1(a,c)
r3 = func1(b,c)
print(r1,r2,r3) func2(2,5,9)
#结果:10 18 45

3.名称空间及变量作用域

名称空间就是存储名字的地方,Python中变量与值的绑定关系的地方。分为三种:内置名称空间、全局名称空间、局部名称空间。

内置名称空间:Python解释器启动时首先加载的

全局名称空间:执行脚本时,以脚本内容为基础,加载全局名称空间

局部名称空间:在运行脚本的过程中,如果调用函数,就会临时产生局部名称空间

内置名称空间和全局名称空间对应的作用域是全局的,而局部名称空间对应的作用域是局部的。

因此我们在脚本里应该尽可能少地定义全局有效的变量,这样耗内存且拖慢运行速度。

变量的作用域是定义的时候就固定了的,对于函数中的参数变量,是在函数定义阶段固定的,跟函数的调用位置不相关。

在函数内定义的变量一般只在函数内部起作用,不能再函数外部使用。

a = 99
print(a)#
def addn():
a = 100#这里定义的a只在本函数内部有作用
print(a)
a += 1
print(a)
addn()#100 101
print(a)#
a = 200
print(a)#

4.闭包

上面讲到的函数嵌套定义中的第二部分示例其实就是闭包。闭包返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域。

闭包中内层的函数通过nonlocal关键字可以使得其可以使用外层函数中定义的变量。

下面的例子中,如果n不指定为nonlocal,程序会报错

#实现一个计数器
def counter():
n=0
def incr():
nonlocal n
x=n
n+=1
return x
return incr c=counter()
print(c())#
print(c())#
print(c())#

使用闭包可以延迟计算,先将函数包起来,需要用的时候再调用。

5.装饰器

我们在写Python程序的时候往往需要输出一些日志信息,但是不希望去改变函数内部的代码,那么给函数动态增加如输出日志的功能,可以用装饰器实现。

装饰器有两种:不带参数和带参数的装饰器。

#不带参数的装饰器
import functools
def log(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
#带参数的装饰器
#text是需要传入的参数
import functools
def log1(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))#func.__name__返回变量func对应的函数名
return func(*args, **kw)
return wrapper
return decorator

装饰器的输入是函数,返回值也是函数。将装饰器放在要定义的函数的前面(使用@),即可实现在调用定义的函数的时候会运行一次装饰器。

@log
def now():
print('2019-08-10')
@log1('tt')
def now():
print('2019-08-10')

那么对于上述不带参数的装饰器,调用now()函数的时候的输出如下:相当于执行了now = log(now)

>>>now()
call now():
2019-08-10

对于上述带参数的装饰器,调用now()函数的时候的输出如下:相当于执行了now = log('tt')(now)

>>>now()
tt now():
2019-08-10

多个装饰器可以同时放在函数定义的上面

@log1
@log2
@log3
def now():
pass #相当于:now = log1(log2(log3(now)))

最后放一个装饰器的例子。

用一个装饰器为多个函数加上认证功能,登录成功一次后在超时时间内进行其他操作(运行下一个函数)无需重复登录,超过了超时时间,则必须重新登录。

#装饰器为多个函数加上认证功能,登录成功一次后在超时时间内进行其他操作(运行下一个函数)无需重复登录,超过了超时时间,则必须重新登录
import time,random user = {'name':None, 'login_time':False, 'timeout':0.0000002} def log(func):
def wrapper(*args,**kwargs):
if user['name']:
timeout=time.time()-user['login_time']
if timeout < user['timeout']:
return func(*args,**kwargs)
else:
print("登录超时,请重新登录!")
name=input('name: ').strip()
password=input('pwd: ').strip()
if name == 'tt' and password == '':
user['name']=name
user['login_time']=time.time()
res=func(*args,**kwargs)
return res
return wrapper @log
def first():
print("welcome to login!") @log
def home():
print("welcome to home!") first()
home()

当我们在首次登录后会执行first函数里面的代码,再执行home函数时已经超过超时时间,这时的输出如下,需要再次输入用户名和密码。

name: tt
pwd: 123
welcome to login!
登录超时,请重新登录!
name:

而如果未超过超时时间,home函数能够直接执行,输出:

name: tt
pwd: 123
welcome to login!
welcome to home!

Python--高阶函数、函数嵌套、名称空间及变量作用域、闭包、装饰器的更多相关文章

  1. 【0809 | Day 12】可变长参数/函数的对象/函数的嵌套/名称空间与作用域

    可变长参数 一.形参 位置形参 默认形参 二.实参 位置实参 关键字实参 三.可变长参数之* def func(name,pwd,*args): print('name:',name,'pwd:',p ...

  2. python 函数及变量作用域及装饰器decorator @详解

    一.函数及变量的作用   在python程序中,函数都会创建一个新的作用域,又称为命名空间,当函数遇到变量时,Python就会到该函数的命名空间来寻找变量,因为Python一切都是对象,而在命名空间中 ...

  3. Python入门之函数的嵌套/名称空间/作用域/函数对象/闭包函数

    本篇目录: 一.函数嵌套 二.函数名称空间与作用域 三.函数对象 四.闭包函数 ============================================================ ...

  4. python之函数对象、函数嵌套、名称空间与作用域、装饰器

    一 函数对象 一 函数是第一类对象,即函数可以当作数据传递 #1 可以被引用 #2 可以当作参数传递 #3 返回值可以是函数 #3 可以当作容器类型的元素 二 利用该特性,优雅的取代多分支的if de ...

  5. python基础知识13---函数对象、函数嵌套、名称空间与作用域、装饰器

    阅读目录 一 函数对象 二 函数嵌套 三 名称空间与作用域 四 闭包函数 五 装饰器 六 练习题 一 函数对象 1 函数是第一类对象,即函数可以当作数据传递 #1 可以被引用 #2 可以当作参数传递 ...

  6. python之旅:函数对象、函数嵌套、名称空间与作用域、装饰器

    一 函数对象 一 函数是第一类对象,即函数可以当作数据传递 #1 可以被引用 #2 可以当作参数传递 #3 返回值可以是函数 #3 可以当作容器类型的元素 二 利用该特性,优雅的取代多分支的if de ...

  7. python函数篇:名称空间、作用域和函数的嵌套

    一.名称空间:(有3类) (1)内置名称空间(全局作用域) (2)全局名称空间(全局作用域) (3)局部名称空间(局部作用域) 关于名称空间的查询: x=1 def func(): print('fr ...

  8. Python 函数对象-函数嵌套-名称空间与作用域-闭包函数

    今日内容: 1. 函数对象 函数是第一类对象: 指的是函数名指向的值可以被当中数据去使用 1.可以被引用 2.可以当做参数传给另一个函数 3.可以当做一个函数的返回值 4.可以当做容器类型的元素 2. ...

  9. Python函数02/函数的动态参数/函数的注释/名称空间/函数的嵌套/global以及nolocal的用法

    Python函数02/函数的动态参数/函数的注释/名称空间/函数的嵌套/global以及nolocal的用法 目录 Python函数02/函数的动态参数/函数的注释/名称空间/函数的嵌套/global ...

随机推荐

  1. github项目readme.md文件如何编写

    参考链接:http://blog.csdn.net/Bone_ACE/article/details/48318675

  2. 用户体验要素——产品系统设计方法

    用户体验已经成为了每个互联网人的口头词,特别是互联网产品经理或产品设计师. 的确,对于任何一个互联网产品而言,体验都是非常重要的. 但是具体的用户体验到底指的是哪些方面,界面,UI,还是交互,其中到底 ...

  3. ES 22 - Elasticsearch中如何进行日期(数值)范围查询

    目录 1 范围查询的符号 2 数值范围查询 3 时间范围查询 3.1 简单查询示例 3.2 关于时间的数学表达式(date-math) 3.3 关于时间的四舍五入 4 日期格式化范围查询(format ...

  4. 关于引入js文件乱码的问题

    对于大多数的web页面,我们一般都是使用如下两种编码:UTF-8.GB2312.所以我们只需要同意页面和js编码就可以解决乱码问题: 对于GBK页面引用编码为UTF-8编码的JavaScript文件如 ...

  5. 史上最强Java开发环境搭建

    在项目产品开发中,开发环境搭建是软件开发的首要阶段,也是必须阶段,只有开发环境搭建好了,方可进行开发,良好的开发环境搭建,为后续的开发工作带来极大便利. 对于大公司来说,软件开发环境搭建工作一般是由运 ...

  6. Linux命令(部分)

    LINUX:实现某一功能,命令执行依赖于解释器程序.       内部:属于shell部分       外部:独立于shell解释器程序.       系统结构由外到内:用户 ⇢ 外围程序 ⇢ 硬件  ...

  7. ld: library not found for -

    这几天在做微信登录,总是遇到这个问题,详细如下: ld: library not found for -lWeChatSDK clang: error: linker command failed w ...

  8. js实现3D切换效果

    今天分享一个3d翻转动画效果,js+css3+h5实现,没有框架. 先看下html部分: <div class="box"> <ul> <li> ...

  9. C++ protobuffer 前后端通信 简单应用

    后端发送多个protobuffer消息到前端,前端用socket监听,如何区分消息类型呢? //定义心跳包 DseHeartbeat _DseHeartbeat; DseHeartbeat _DseH ...

  10. Kibana对数据的可视化

    基于上一篇的操作,我们已经获得了数据,接下来我们就要处理数据,因此选用了Kibana 先来介绍一下, Kibana是一个针对Elasticsearch的开源分析及可视化平台,用来搜索.查看交互存储在E ...