Python--高阶函数、函数嵌套、名称空间及变量作用域、闭包、装饰器

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‘: 0, ‘1‘: 1, ‘2‘: 2, ‘3‘: 3, ‘4‘: 4, ‘5‘: 5, ‘6‘: 6, ‘7‘: 7, ‘8‘: 8, ‘9‘: 9}
        return DIGITS[x]
    return reduce(lambda y,z:y*10+z, map(str2num,s))
print(‘9748‘)#9748
#将字符串转化成浮点数
from functools import reduce
def str2float(s):
    DIGITS = {‘0‘: 0, ‘1‘: 1, ‘2‘: 2, ‘3‘: 3, ‘4‘: 4, ‘5‘: 5, ‘6‘: 6, ‘7‘: 7, ‘8‘: 8, ‘9‘: 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)#99
def addn():
    a = 100#这里定义的a只在本函数内部有作用
    print(a)
    a += 1
    print(a)
addn()#100 101
print(a)#99
a = 200
print(a)#200

4.闭包

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

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

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

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

c=counter()
print(c())#1
print(c())#2
print(c())#3

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

5.装饰器

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

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

#不带参数的装饰器
import functoolsdef log(func):    @functools.wraps(func)
    def wrapper(*args, **kw):
        print(‘call %s():‘ % func.__name__)
        return func(*args, **kw)
    return wrapper
#带参数的装饰器
#text是需要传入的参数import functoolsdef 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 == ‘123‘:
            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!

原文地址:https://www.cnblogs.com/taotingz/p/11332079.html

时间: 2024-08-15 11:29:35

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

python_day04 函数嵌套 名称空间和作用域 闭包 装饰器 迭代器 生成器 列表解析 三元表达式 生成器表达式

本节课重要知识点内容如下: 函数嵌套 名称空间和作用域 闭包 装饰器 迭代器 生成器 列表解析 三元表达式 生成器表达式 1.函数嵌套 函数的嵌套调用:在调用一个函数的过程中,又调用了其他函数函数的嵌套定义:在一个函数的内部,又定义另外一个函数 def bar(): print('from nbar')def foo(): print('from foo') bar()foo()def max2(x,y): if x > y: return x else: return ydef max4(a,

函数对象,函数的嵌套,名称空间与作用域,闭包,装饰器,迭代器,内置函数

一,函数对象 函数对象:函数是第一类对象,即函数可以当做数据传递 1,可以被引用 2,可以做参数的传递 3,返回值可以是函数 4,可以当作容器类型的元素 二,函数嵌套 1,函数的嵌套调用 2,函数的嵌套定义 三,名称空间与作用域 名称空间:存放名字的地方叫名称空间,存放这些值与名字的绑定关系 查看内置名称的两种方法: 三种名称空间 1,内置名称空间:随着python解释器的启动而产生 2,全局名称空间:文件的执行会产生全局名称空间,指的是文件级别定义的名字都会放入该空间 3,局部名称空间:调用函

【Python笔记】Python的几个高级语法概念浅析:lambda表达式 &amp;&amp; 闭包 &amp;&amp; 装饰器

本文主要记录自己对几个高级语法概念的理解:匿名函数.lambda表达式.闭包.装饰器. 这几个概念并非Python特有,但本文只限于用Python做说明. 1. 匿名函数 匿名函数(anonymous function)是指未与任何标识符绑定的函数,多用在functional programming languages领域,典型应用场合: 1) 作为参数传给高阶函数(higher-order function ),如python中的built-in函数filter/map/reduce都是典型的

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

一.函数及变量的作用 在python程序中,函数都会创建一个新的作用域,又称为命名空间,当函数遇到变量时,Python就会到该函数的命名空间来寻找变量,因为Python一切都是对象,而在命名空间中,都是以字典形式存在着,这些变量名,函数名都是索引,而值就是,对应的变量值和函数内存地址.在python中可以用globals()查看全局变量,locals()局部变量. >>> global_v = '全局变量' >>> def func(): ... local_v = '

函数名的应用(第一对象) 闭包 装饰器

函数名的应用(第一对象). # 1,直接打印函数名得到的是函数的内存地址 <function func1 at 0x0000000002876B70> # print(func1) #2,函数名可以赋值运算. # def func1(): # print(666) # f1 = func1 # f1() # 3, 函数名可以作为函数的参数. # def func1(): # print(666) # # def func2(x): # x() # print(555) # func2(func

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

阅读目录 一 函数对象 二 函数嵌套 三 名称空间与作用域 四 闭包函数 五 装饰器 六 练习题 一 函数对象 一 函数是第一类对象,即函数可以当作数据传递 #1 可以被引用 #2 可以当作参数传递 #3 返回值可以是函数 #3 可以当作容器类型的元素 二 利用该特性,优雅的取代多分支的if def foo(): print('foo') def bar(): print('bar') dic={ 'foo':foo, 'bar':bar, } while True: choice=input(

python基础(3):函数对象、函数嵌套、名称空间与作用域、装饰器

函数对象 函数嵌套 名称空间与作用域 闭包函数 装饰器 练习 一 函数对象 #1 可以被引用 def max(x, y): return x if x > y else y func = max print(func(1, 2)) #2 可以当作参数传递 def max(x, y): return x if x > y else y def max_1(x, func): return func(x, 1) print(max_1(2, max)) #3 返回值可以是函数 #4 可以当作容器类

【Python基础】高阶函数+函数嵌套+闭包 ==装饰器

高阶函数+函数嵌套+闭包 == 装饰器 一 什么是装饰器 二 装饰器需要遵循的原则 三 实现装饰器知识储备 四 高阶函数 五 函数嵌套 六 闭包 七 无参装饰器 八 装饰器应用示例 九 超时装饰器 参考: https://www.cnblogs.com/linhaifeng/articles/6140395.html https://www.cnblogs.com/haiyan123/p/8387769.html 原文地址:https://www.cnblogs.com/XJT2018/p/11

函数嵌套 ,名称空间与作用域 ,闭包函数 ,装饰器 ,迭代器, 生成器 三元表达式,列表解析,生成器表达式 递归与二分法, 内置函数

函数嵌套名称空间与作用域闭包函数装饰器迭代器生成器三元表达式,列表解析,生成器表达式递归与二分法内置函数--------------------------------------------函数的嵌套调用:在调用一个函数的过程中,又调用了其他函数函数的嵌套定义:在一个函数的内部,又定义另外一个函数def max(x,y): if x>y: return x else: return ydef max1(a,b,c,d): res=max(a,b) res2=max(res,c) res3=ma