【python知识点总结】第四章 函数式编程


​ 这是一种抽象程度很高的编程范式,允许把函数本身作为参数传入另一个函数,还允许返回一个函数

一 高阶函数

一个函数可以接收另一个函数作为参数,则该函数为高阶函数(让函数的参数能够接收别的函数)

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课程进行记录

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值