这是一种抽象程度很高的编程范式,允许把函数本身作为参数传入另一个函数,还允许返回一个函数
一 高阶函数
一个函数可以接收另一个函数作为参数,则该函数为高阶函数(让函数的参数能够接收别的函数)
def add(x,y,f):
return f(x)+f(y)
print(add(-5,6,abs)) # 11
变量可以指向函数
x=abs(-10)
print(x) # 10
函数可以赋值给变量
f=abs
print(f) # <built-in function abs>
print(f(-10)) # 10
函数名也是变量
abs=10
1、map/reduce(fun,list)
map()函数接收两个参数(函数和Iterable),map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回,需要用**list()**函数获取所有结果并返回list
def f(x):
return x**2
r=map(f,[1,2,3,4])
print(list(r)) # 依次用函数f作用于[1,2,3,4]得——[1, 4, 9, 16]
L=list(map(str,[1,2,3,4,5])) # 将数字转为字符串,用List输出
print(L) # ['1', '2', '3', '4', '5']
**reduce()**将一个函数作用在一个序列 [x1, x2, x3, ...] 上,接收两个参数即传入的函数必须有**两个参数**,把结果继续和序列的下一个元素做**累积**计算
reduce(f,[x1, x2, x3, …])=f(f(f(x1,x2),x3),x4)
from functools import reduce
def add(x,y):
return x+y
a=reduce(add,[1,3,5,7])
print(a) #依次将add作用于1,3得4,再将add作用于4,5得9,再将add作用于9,7得——16
exp:将字符串转为数字
from functools import reduce
# 法1:
def fn(x,y):
return x*10+y
def char2num(s):
digits={'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}
return DIGITS[s]
a=reduce(fn,map(char2num,'12345'))
print(a) # 12345
DIGITS = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
# 法2
def str2int(s):
def fn(x,y):
return x*10+y
def char2num(s):
return DIGITS[s]
return reduce(fn,map(char2num,s))
print(str2int('1234')) # 1234
# 法3
def char2num(s):
return DIGITS[s]
def str2int(s):
return reduce(lambda x, y: x * 10 + y, map(char2num, s)) #lambda函数进一步简化
print(str2int('123')) # 123
exp:将首字母变大写,其他小写
def normalize(word):
word=word[0].upper()+word[1:].lower()
return word
L=list(map(normalize,['adam','LISA']))
print(L) # ['Adam', 'Lisa']
2、filter(fun,list)
**filter()过滤函数(函数和序列),用于过滤序列,将传入的函数作用于每个元素,根据返回值是True还是False决定保留还是丢弃该元素,filter()返回Iterator,需要用list()**函数获取所有结果并返回list
def id_odd(n):
return n%2==1 # 过滤偶数
L=filter(id_odd,[1,2,3,4,5,6,7,8]) # id_odd依次作用于[1,2,3,4,5,6,7,8]判断真假
print(list(L)) # 转为list输出——[1, 3, 5, 7]
exp:求素数
def _odd_iter(): # 构造从3开始的奇数序列
n=1
while True:
n=n+2
yield n
def _not_divisible(n): # 构造筛选函数
return lambda x:x%n>0
def primes(): # 构造生成器
yield 2
it=_odd_iter()
while True:
n=next(it)
yield n
it=filter(_not_divisible(n),it) # 进行筛选
for n in primes():
if n<10:
print(n) # 2 3 5 7
else:
break
exp:构造回数
def is_palindrome(n):
n1=str(n)
return n1==str(n)[::-1] # [::-1]表示倒序复制原字符串
L=filter(is_palindrome,range(1,100))
print(list(L)) # [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99]
3、sorted
sorted()函数可以进行排序
对 list排序
L=sorted([23,2,34,2,65,11])
print(L)
对 list按照绝对值排序
L1=sorted([21,45,4,-3,-32,5],key=abs) # 用ke自定义排序规则
print(L1)
对字符串进行排序
L2=sorted(['bob','about','dog','Zoo']) # 按ASCII大小进行排序
print(L2) # ['Zoo', 'about', 'bob', 'dog']
L3=sorted(['bob','about','dog','Zoo'],key=str.lower) # 直接按字母排序
print(L3) # ['about', 'bob', 'dog', 'Zoo']
倒序排序
L4=sorted([23,2,34,2,65,11],reverse=True)
print(L4) # [65, 34, 23, 11, 2, 2]
exp:成绩排序
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
# 按名字排
def by_name(t):
return t[0].lower()
L1=sorted(L,key=by_name)
print(L1)
# 按成绩降序排
def by_score(n):
return n[1]
L2=sorted(L,key=by_score,reverse=True)
print(L2)
二 返回函数
将函数作为结果值返回
def lazy_sum(*args):
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum # 返回函数
f=lazy_sum(1,2,3)
print(f) # 返回的不是结果,是lazy_sum中的sum函数
print(f()) # 计算求和结果——6
闭包:返回函数在定义的内部引用了局部变量,当一个函数返回一个函数后,内部的局部变量还被新函数引用。返回函数不能引用任何循环变量或者后续会发生变化的量
引用循环变量:再创建一个函数
def count():
def f(j):
def g(): # 为循环变量新定义一个函数
return j*j
return g
fs=[]
for i in range(1,4):
fs.append(f(i))
return fs
f1,f2,f3=count()
print(f1()) # 1
print(f2()) # 4
print(f3()) # 9
在闭包中要对外层变量赋值需要加 nonlocal x,否则解释器会将x当作局部变量
def inc():
x=0
def fn():
nonlocal x
x=x+1
return x
return fn
f=inc()
print(f()) # 1
print(f()) # 2
print(f()) # 3
三 匿名函数lambda
如果一个函数有一个返回值,并且只有一句代码,可以用lambda简化
语法:lambda x,y: x*10+y——:前面表示函数参数(任意个),:后面为表达式,只能有一个表达式,参数可有可无。返回值为表达式
的结果
print(list(map(lambda x:x**2,[1,2,3,4,5,6]))) # [1, 4, 9, 16, 25, 36]
将匿名函数赋值给一个变量
f=lambda x:x+10
print(f) # <function <lambda> at 0x000001E5C9EFF158>——打印的lambda内存地址
print(f(3)) # 13——调用函数才能返回值,即将3传给x然后计算x+10
lambda的参数形式
# 无参数
fn1=lambda :100
print(fn1()) # 100
# 一个参数
fn2=lambda x:100+x
print(fn2(3)) # 103
# 默认参数(缺省参数)
fn3=lambda y,x=3:x+10
print(fn3(4)) # 13
print(fn3(4,1)) # 11
# 可变参数(不定长参数)
fn4=lambda *x:x
print(fn4(10)) # (10,)
print(fn4(10,20)) # (10,20)
# 关键字参数
fn5=lambda **x:x
print(fn5(name='chen',age=18)) # {'name': 'chen', 'age': 18}
带判断的 lambda
fn1=lambda x,y:y if x>y else x # 通过三目运算进行判断
print(fn1(10,20)) # 10
lambda按照字典key值排序
students=[{'姓名':'aaa','年龄':18},{'姓名':'bbb','年龄':45},{'姓名':'ccc','年龄':22},{'姓名':'ddd','年龄':17}]
students.sort(key=lambda x:x['姓名'],reverse=True)
print(students)
四 装饰器decorator
在代码运行期间动态增加功能的方式即装饰器
def log(func):
def wrapper(*args,**kw):
print('call %s():'%func.__name__)
return func(*args,**kw)
return wrapper
@log
def now():
print('231')
五 偏函数
同设定参数的默认值,降低函数调用的难度
偏函数的作用为把一个函数的某些参数固定住(设置默认值),返回一个新的函数
# 普通进制转换
print(int('12345')) # 12345
print(int('123',base=8)) # 八进制——83
def int2(x,base=2): # 固定base=2
return int(x,base)
print(int2('10000')) # 1
创建偏函数时可以接收函数对象、*args、**kw这三个参数
本文根据廖雪峰老师python课程和黑马程序员python课程进行记录