Python入门基础二——函数式编程

匿名函数

当我们在传入函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便。如:list(map(lambda x:x * x,[1,2,3,4,5]))实际上就相当于

def f(x):
    return x * x

关键字lambda表示匿名函数,冒号前面的x表示函数参数。匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。同样,也可以把匿名函数作为返回值返回,比如:

def build(x, y):
    return lambda: x * x + y * y

用匿名函数可以简化代码,一个筛选出奇数例子如下:

def is_odd(n):
    return n % 2 == 1
L = list(filter(is_odd,range(1,20)))#用普通函数

L = list(filter(lambda x : x % 2 == 1,range(1,20)))#用匿名函数

装饰器

假设我们要增强函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。我们要定义一个能打印日志的decorator,可以定义如下:

def log(func):
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper

再定义一个函数now()前面用@语法将decorator置于函数的定义处,相当于执行了语句:now = log(now)

@log
def now():
    print('2019-1-4')

调用now()函数,不仅会运行now()函数本身,还会在运行now()函数前打印一行日志:

>>> now()
call now():
2019-1-4

这里需要注意经过decorator装饰之后的函数,它们的__name__已经从原来的'now'变成了'wrapper',所以,需要把原始函数的__name__等属性复制到wrapper()函数中,Python内置的functools.wraps就是用来干这件事的,所以,一个完整的decorator的写法如下:

import functools

def log(func):
    @functools.wraps(func)
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper

写了一个能打印出函数执行时间的例子:

import time, functools
def metric(fn):
    @functools.wraps(fn)
    def wrapper(*args, **kw):
        start_time = time.time()
        ret = fn(*args, **kw)
        end_time = time.time()
        print('%s executed in %s ms' % (fn.__name__, (end_time - start_time)))
        return ret
    return wrapper

@metric
def fast(x,y):
    time.sleep(0.1)
    return x + y
f = fast(11,22)

偏函数

Python的functools模块提供了很多有用的功能,其中一个就是偏函数(Partial function)。它可以固定住原函数的部分参数,比如int()函数可以把字符串转换为整数,当仅传入字符串时,int()函数默认按十进制转换,int()函数还提供额外的base参数,默认值为10。如果传入base参数,就可以做N进制的转换:

>>> int('12345', base=8)
5349
>>> int('12345', 16)
74565

假设要转换大量的二进制字符串,每次都传入int(x, base=2)非常麻烦,可以定义一个int2()的函数,默认把base=2传进去,functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义int2(),如:

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

所以,简单总结偏函数的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。上面的新的int2函数,仅仅是把base参数重新设定默认值为2,但也可以在函数调用时传入其他值。

python的程序入口

对于很多编程语言来说,程序都必须要有一个入口,比如C,C++,C,C++都需要有一个main函数作为程序的入口,也就是程序的运行会从main函数开始。而Python则不同,它属于脚本语言,不像编译型语言那样先将程序编译成二进制再运行,而是动态的逐行解释运行。也就是从脚本第一行开始运行,没有统一的入口。
假设我们有一个const.py文件:

PI = 3.14
def main():
    print("PI:", PI)
main()
# 运行结果:PI: 3.14

然后写一个计算面积的程序,用到const.py里的PI:

from const import PI
def calc_round_area(radius):
    return PI * (radius ** 2)
def main():
    print("round area: ", calc_round_area(2))
main()

'''
运行结果:
PI: 3.14
round area:  12.56
'''

可以看到const.py中的main函数也被运行了,实际上我们不希望它被运行,这时就需要if __name__ == '__main__'了:

PI = 3.14
def main():
    print("PI:", PI)
if __name__ == "__main__":
    main()

运行const.py,输出如下:PI: 3.14,运行计算面积的程序,输出如下:round area: 12.56,所以if __name__ == '__main__'相当于Python模拟的程序入口,这是一种编程的习惯.
__name__是内置变量,表示当前模块的名字,如果一个.py文件(模块)被直接运行时,则其没有包结构,其__name__值为__main__,即模块名为__main__
所以,if __name__ == '__main__'的意思是:当.py文件被直接运行时,if __name__ == '__main__'之下的代码块将被运行;当.py文件以模块形式被导入时,if __name__ == '__main__'之下的代码块不被运行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值