设为首页 收藏本站
查看: 649|回复: 0

[经验分享] Python中的函数、装饰器

[复制链接]

尚未签到

发表于 2017-4-28 12:14:31 | 显示全部楼层 |阅读模式


  • map()函数接收两个参数,一个是函数,一个是序列,map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回。


>>> s = ['AASDa', 'dendY']

>>> def formatStr(ss):

return ss[0].upper() + ss[1:len(ss)].lower()



>>> v = formatStr('aaaB')

>>> v

'Aaab'

>>> map(formatStr, s)

<map object at 0x000000000320A668>

>>> for v in map(formatStr, s):

print(v)





Aasda

Dendy













  • reduce把一个函数作用在一个序列[x1, x2, x3...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:

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





>>> L = [2, 3, 4]

>>> def prod(a, b):

return a * b

>>>

>>> from functools import *

>>> reduce(prod, L)

24

>>>







  • filter函数,方法同map,目的是过滤list中符合条件的元素:






>>> s = [1, 2, -3, -5]

>>> def notLt0(x):

return x >= 0



>>> filter(notLt0, s)

<filter object at 0x000000000320A940>

>>> for v in filter(notLt0, s):

print(v)





1

2

>>>





如上的示例,定义一个notLt0的方法,该方法用于判断元素是否大于等于0,是则返回True,否则返回False。而filter则会将列表s的每一个元素作为参数调用notLt0方法,最后将所有返回True的元素重新组装成一个list返回。





  • 匿名函数:无须定义函数的名称,格式如下:

fn = lambda 函数参数列表: 函数体




其中fn为返回的匿名函数,例如:


'''

匿名函数

'''

f = lambda x : x * x

print(f(2))







  • 函数的闭包,类似javascript的闭包,即外部函数返回内部函数的引用,内部函数可能持有外部函数变量的引用,例如:


'''

闭包

'''

def count():

    fs = []

    for i in range(1, 4):

        def f():

            print(i)

            return i * i

        fs.append(f)        

    return fs



f1, f2, f3 = count()

print('before execute...')   

print(f1()) # 输出:9

print(f2()) # 输出:9

print(f3()) # 输出:9

print('after execute...')





由于每次执行fn()时,i的值都变为了3,所以输出的结果并非预期的1,4,9,解决这种问题有多种方式,可以再定义一层闭包,也可以将fs中的元素修改为f函数的执行结果,而不是函数引用。





  • 装饰器(decorator),包装目标函数,在不改变原目标函数的情况下,对其进行包装,实现更多的功能。

  例如:实现一个打印日志的装饰器:






'''

装饰器

'''

# 定义一个装饰器(decorator)

def log(fn):

    def wrapper(*args, **kw):

        print('call : %s' % (fn.__name__))

        return fn(*args, **kw)

    return wrapper



@log

def func():

    print ('hello!')



func()





其中,log函数为一个装饰器,除了完成fn函数本身的功能外,还添加了打印日志的功能,log函数返回一个装饰函数wrapper,打印的结果:




call : func

hello!





Python中使用@符号来表示装饰器(不是java的注解,形式类似),在执行func函数时,解释器看到@符号标识,会先执行log方法,并将func函数作为参数,此时func函数依然存在,但是同名的func变量会指向wrapper函数:



print(func.__name__)




输出wrapper,同:




func = wrapper(*args, **kw):

         print('call : %s' % (fn.__name__))

         return fn(*args, **kw)





所以,执行func()函数其实执行的是wrapper函数。







上边为最简单的装饰器,如果我们要实现可自定义参数的装饰器呢?


# 自定义文本的装饰器

def log(text):

    def decorator(fn):

        def wrapper(*args, **kw):

            print('log : %s, function name : %s. ' % (text, fn.__name__))

            fn(*args, **kw)

        return wrapper

    return decorator



@log('this is a log text.')

def func():

    print ('hello!')



func()

print(func.__name__) # 输出:wrapper





如上,我们需要再定义一个函数decorator来接收我们定义的参数信息,除了上边的执行过程外,在调用func函数时,解释器会先执行log和decorator函数,最后在执行wrapper函数,形式如下:



func = log(自定义参数)(func)





  • 偏函数,functools.partial,固定函数参数,形成新的函数:





如果我们需要在转换为int的时候确定进制,Python提供了int方法:

int(x, base = 10)




base为此时x的进制数,默认为10,我们写一个将二进制字符串转换为int的方法:




def int2(x):

    return int(x, base = 2)

s = int2('110')

print (s) # 输出6





但是,其实Python已经为我们做了这样的事情,那就是利用functools.partial的方法:




int2 = functools.partial(int, base = 2)

s = int2('110')

print (s) # 输出6





当然,该函数用法有很多,例如将max函数默认与一些元素比较:




max2 = functools.partial(max, 10, 20, 30)

s = max2(1, 2, 3, 40)

print(s) # 输出:40


s = max2(1, 2, 3)

print(s) # 输出:30









这样,max函数在比较的元素中,默认会加入10,20,30了。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-370417-1-1.html 上篇帖子: Python的编码规范PEP8 下篇帖子: python面向对象(下)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表