将计算视为函数而非指令
纯函数式编程:不需要变量,没有副作用,测试简单
支持高阶函数,代码简介
Python支持的函数式编程
Python中的高阶函数
>>> def add(x,y,f):
... return f(x) + f(y)
...
>>> add(1,2,abs)
3
# map(function, iterable, ...)
# python2 返回列表,py3返回迭代器
# 第一个参数function以参数序列中的每一个元素调用 function 函数
def format_name(s):
return s.capitalize() # 首字母大写,其他字母小写
print(list(map(format_name, ['adam', 'LISA', 'barT'])))
# reduce(function, iterable[, initializer]):
# 先对集合中的1,2进行functino的运算,在将返回结果以此与后面元素进行计算,最后得到一个结果(第三个参数是初始值)
# 求积
def prod(x, y):
return x * y
print reduce(prod, [2, 4, 5, 7, 12])
# filter(function, iterable)
# 用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。
# Pyhton2.7 返回列表,Python3.x 返回迭代器对象
# filter()过滤出1~100中平方根是整数的数
import math
def is_sqr(x):
a = int(math.sqrt(int(x)))
return a * a == int(x)
print(list(filter(is_sqr,range(1,101))))
# sorted()也是一个高阶函数,它可以接收一个比较函数来实现自定义排序
# 比较函数的定义是,传入两个待比较的元素 x, y,
# 如果 x 应该排在 y 的前面,返回 -1,
# 如果 x 应该排在 y 的后面,返回 1,
# 如果 x 和 y 相等,返回 0。
# 忽略大小写排序
def cmp_ignore_case(s1, s2):
s1 = s1.lower()
s2 = s2.lower()
if s1 < s2 :
return -1
if s1 > s2 :
return 1
return 0
print(sorted(['bob', 'about', 'Zoo', 'Credit'], cmp_ignore_case))
内层函数引用了外层函数的变量(参数也算变量),然后返回内层函数的情况,称为闭包
闭包的特点是返回的函数还引用了外层函数的局部变量,所以,要正确使用闭包,就要确保引用的局部变量在函数返回后不能变。举例如下:
def count():
fs = []
for i in range(1,4):
def f():
return i * i
fs.append(f)
return fs
f1,f2,f3 = count()
>>> f1()
9 # 因为f1现在才计算i*i,但现在i的值已经变为3
# 正确写法:输出:1 4 9
def count():
fs = []
for i in range(1, 4):
def f(j):
def g():
return j * j
return g
r = f(i)
fs.append(r)
return fs
f1, f2, f3 = count()
print(f1(), f2(), f3())
Python匿名函数
>>> map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9])
[1, 4, 9, 16, 25, 36, 49, 64, 81]
# 利用匿名函数简化以下代码:
def is_not_empty(s):
return s and len(s.strip()) > 0
filter(is_not_empty, ['test', None, '', 'str', ' ', 'END'])
# 结果
print filter(lambda s:s and len(s.strip()) > 0 , ['test', None, '', 'str', ' ', 'END'])
Python中decorator装饰器
>>> def f1(x):
... return x * 2
...
>>> def new_fn(f): # 装饰器函数
... def fn(x):
... print("call"+f.__name__+"()")
... return f(x)
... return fn
(1)
>>> g = new_fn(f1)
>>> g(2)
callf1()
4
(2)
>>> f1 = new_fn(f1) # f1的原始定义被彻底隐藏了
>>> f1(2)
callf1()
4
@
语法就是为了简化装饰器的调用>>> @new_fn
... def f1(x):
... return x*2
>>> f1(2)
callf1()
4
相当于:
def f1(x):
return x*2
f1 = new_fn(f1)
# 打印函数调用时间
# 可获取任意数量参数
import time
def performance(f):
def fn(*args , **kw):
st = time.time()
r = f(*args , **kw)
ed = time.time()
print('call %s() in %fs' %(f.__name__,(ed-st)))
return r
return fn
@performance
def factorial(n):
return reduce(lambda x,y: x*y, range(1, n+1))
print factorial(10)
>>> def log(prefix):
... def log_decorator(f):
... def wrapper(*args,**kw):
... print('[%s] %s()...' %(prefix,f.__name__))
... return f(*args,**kw)
... return wrapper
... return log_decorator
>>> @log('DEBUG')
... def test():
... return x*2
...
=====相当于=====
log_decorator = log('DEBUG')
@log_decorator
def test(x):
return x*2
===============
>>> test(2)
[DEBUG] test()...
4
import time
def performance(unit):
def fn(f):
def wrapper(*args,**kw):
st = time.time()
r = f(*args,**kw)
ed = time.time()
t = (ed-st)*1000 if unit == 'ms' else (ed-st)
print('call %s() in %f%s' %(f.__name__,t,unit))
return r
return wrapper
return fn
@performance('ms')
def factorial(n):
return reduce(lambda x,y: x*y, range(1, n+1))
print factorial(10)
import functools
def log(f):
@functools.wraps(f)
def wrapper(*args, **kw):
print 'call...'
return f(*args, **kw)
return wrapper
# 带参数的@decorator
import time, functools
def performance(unit):
def pref_decorator(f):
@functools.wraps(f)
def wrapper(*args, **kw):
t1 = time.time()
r = f(*args, **kw)
t2 = time.time()
t = (t2 - t1) * 1000 if unit=='ms' else (t2 - t1)
print 'call %s() in %f %s' % (f.__name__, t, unit)
return r
return wrapper
return pref_decorator
@performance('ms')
def factorial(n):
return reduce(lambda x,y: x*y, range(1, n+1))
print factorial.__name__
Python中的偏函数
>>> int('12345', base=8)
5349
>>> int('12345', 16)
74565
def int2(x, base=2):
return int(x, base)
>>> int2('1000000')
64
functools.partial
就是帮助我们创建一个偏函数的,不需要我们自己定义int2(),可以直接使用下面的代码创建一个新的函数int2:import functools
int2 = functools.partial(int,base=2)
>>> int2('1000000')
64
functools.partial
可以把一个参数多的函数变成一个参数少的新函数,少的参数需要在创建时指定默认值,这样,新函数调用的难度就降低了。# sorted自定义(忽略大小写升序排序)
# Python2 写法
import functools
sorted_ignore_case = functools.partial(sorted,cmp=lambda s1,s2:cmp(s1.lower(),s2.lower()))
print sorted_ignore_case(['bob', 'about', 'Zoo', 'Credit'])
# Python3 写法
>>> def cmp(s1,s2):
... s1 = s1.lower()
... s2 = s2.lower()
... if s1 < s2 :
... return -1
... elif s1 > s2 :
... return 1
... else:
... return 0
...
>>> sorted_ignore_case = functools.partial(sorted,key=(functools.cmp_to_key(cmp)))
>>> print(sorted_ignore_case(['bob','abount','Zoo','Credit']))
['abount', 'bob', 'Credit', 'Zoo']
# functools.cmp_to_key()将py2的cmp()过渡到py3
# 或者这样
sorted_ignore_case = functools.partial(sorted, reverse=Ture, key=lambda x:x.lower())
print(sorted_ignore_case(['bob', 'about', 'Zoo', 'Credit']))