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. Webpack 下使用 web workers 及 基本原理 和 应用场景

    _ 阅读目录 一:web workers的基本原理 二:web Workers 的基本用法 三:在webpack中配置 Web Workers 四:Web Worker的应用场景 回到顶部 一:web ...

  2. 深入理解Java中的锁(三)

    ReadWriteLock接口 读写锁维护一对关联锁,一个只用于读操作,一个只用于写操作.读锁可以由多个线程同时持有,又称共享锁.写锁同一时间只能由一个线程持有,又称互斥锁.同一时间,两把锁不能被不同 ...

  3. 【Python-Django】浏览器同源策略

    1995年,同源政策由 Netscape 公司引入浏览器.目前,所有浏览器都实行这个政策. 同源策略是浏览器的一个安全功能,不同源的客户端脚本(js文件)在没有明确授权的情况下,不能读写对方资源.只有 ...

  4. 用大白话告诉你 :Java 后端到底是在做什么?

    阅读本文大概需要 6 分钟. 作者:黄小斜 新手程序员通常会走入一个误区,就是认为学习了一门语言,就可以称为是某某语言工程师了.但事实上真的是这样吗?其实并非如此. 今天我们就来聊一聊,Java 开发 ...

  5. ASP.NET Core MVC 之局部视图(Partial Views)

    1.什么是局部视图 局部视图是在其他视图中呈现的视图.通过执行局部视图生成的HTML输出呈现在调用视图中.与视图一样,局部视图使用 .cshtml 文件扩展名.当希望在不同视图之间共享网页的可重用部分 ...

  6. 使用jvisualvm.exe工具远程监视tomcat的线程运行状态

    一.简述 在web项目中,常使用tomcat作为web容器.代码编写的时候,由于业务需要,也常会使用线程机制.在系统运行一段时间之后,若出现响应慢或线程之间出现死锁的情况,要查出问题所在,需要使用jd ...

  7. jQuery插件之路(三)——文件上传(支持拖拽上传)

    好了,这次咱一改往日的作风,就不多说废话了,哈哈.先贴上源代码地址,点击获取.然后直接进入主题啦,当然,如果你觉得我有哪里写的不对或者欠妥的地方,欢迎留言指出.在附上一些代码之前,我们还是先来了解下, ...

  8. 数据结构之稀疏矩阵C++版

    //只是简单的演示一下,这个实际运用视乎不怎么多,所以java版不再实现 /* 希疏矩阵应用于对数据的压缩,仅仅保留不为0的数据 稀疏矩阵的转置,可以由多种方式,下面演示的稍显简单,时间复杂度略高O( ...

  9. STL set 详细用法

    一个集合(set)是一个容器,它其中所包含的元素的值是唯一的. 用到的库 #include <set> 定义 最简单: set<int> a; set和其他的stl一样,都支持 ...

  10. 0x33 同余

    目录 定义 同余类与剩余系 费马小定理 欧拉定理 证明: 欧拉定理的推论 证明: 应用: 定义 若整数 $a$ 和整数 $b$ 除以正整数 $m$ 的余数相等,则称 $a,b$ 模 $m$ 同余,记为 ...