lambda表达式
from math import sin
def my_sin(x):
s=round(sin(x),2)
return s
my_sin=lambda x:round(sin(x),2)
#参数列表: 函数的返回值
a=[1,3,4,5]
#两个my_sin是一个意思
b=map(my_sin,a)
print(list(b))
改造方式
1.检查是否能精炼函数体
2.删除关键字:def,函数名,括号,return
3.合并为一行
lambda表达式不需要函数名,直接作为一个匿名函数使用
a=['213','232132141','23','21312432']
def longstr(s):
return len(s)>3
b=filter(longstr,a)
print(list(b))
#上下等价
c=list(filter(lambda s:len(s)<4,a))
print(c)
def my_add(x,y):
return x**2+y**2
print(my_add(2,3))
#上下等价
f=lambda x,y:x**2+y**2
print(f(2,3))
如果函数本身不需要传参,那么lambda后面确实不用加参数
题目:函数转lambda
以下函数求 xⁿ + 2 的值,请将其改写为lambda表达式并测试功能。
def calc(x, n):
s = x ** n + 2
return s
def calc(x, n):
s = x ** n + 2
return s
f=lambda x,n:x**n+2
print(f(5,3))
以下是一个传统的求和函数,可以计算从
1 到 指定数字 n 之间的整数总和。
def calc(n):
res = 0
for i in range(n + 1):
res += i
return res
请使用lambda表达式实现同样的功能,然后求1~100的累加和。
提示:可以通过 sum、range 等方法,把循环求和简化为单行代码。
x=lambda n:sum(list(range(n+1)))
print(x(100))
题目:无参数lambda表达式
某机构的数据模拟岗位,经常会用到一个功能,就是生成100个1到50之间的随机数并放入一个列表中。
传统方式下,实现此功能需要写一个循环或列表生成式。但总是这样重复书写非常繁琐。
因此请使用lambda表达式制作一个函数,可以自动返回一个列表,其中含有100个1~50之间的随机数。然后调用该函数得到一个列表并打印测试。
import random
my_list=[]
def list_tool():
for i in range(50):
my_list.append(random.randint(1,50))
print(my_list)
list_tool()
#上下等价,下面用了列表生成式
my_fun = lambda: [random.randint(1, 50) for _ in range(100)]
print(my_fun())
题目:lambda作参数
以下是某个班级的学生成绩,请使用高阶函数 filter 将及格的分数过滤出来。但是不要单独编写自定义函数,而是直接在 filter 中用 lambda 表达式写出过滤函数。
vals = [97, 65, 43, 75, 59, 82, 46, 71]
vals = [97, 65, 43, 75, 59, 82, 46, 71]
print(list(filter(lambda s:int(s)>60,vals)))
我们已经学过,sorted函数可以对字符串按照字母ASCII码顺序进行排序。只不过大写字母与小写字母的ASCII码位不同,因而会出现 ‘C’ < ‘a’ 的情况,不符合题目“不区分大小写的要求”。
现在有以下列表,其中包含多个英文人名,并且需要不区分大小写排序。请使用sorted与 lambda 表达式完成此功能:
names = [‘Emily’, ‘olivia’, ‘sophia’, ‘ava’, ‘Grace’, ‘ella’]
names = ['Emily', 'olivia', 'sophia', 'ava', 'Grace', 'ella']
print(sorted(names,key=lambda s:s.lower()))
Reduce函数
reduce(函数名,可迭代对象)
from functools import reduce
def my_add(x,y):
return x*y
print(reduce(my_add,[3,55,3,5]))
#先传两个参,然后返回值传入下次的参数,再补充列表第三个参数
# 计算后返回结果,最后补充第四个参数,得到结果
但是再看一种情况
def sq_add(x,y):
return x**2+y**2
print(reduce(sq_add,[2,3,4]))
得到的结果是185,即(4+9)^2+4*2
为了得到三个数的平方和
需要改写一下程序
def sq_add(x,y):
return x+y**2
print(reduce(sq_add,[2,3,4],0))
加一个初始值,因为实际工作的,只需要y的平方,前面x仅仅接受上一个y平方的结果
也可以用lambda函数一气呵成
print(reduce(lambda x,y:x+y**2,range(1,10),0))
也可以用来干字符串
from functools import reduce
c=['张宇','汤家凤','李永乐','王式安','高昆轮']
print(reduce(lambda x,y:x+y[0],c,''))
张汤李王高
题目:reduce基本用法
请使用reduce和filter等高阶函数计算0~100之间所有偶数的和。
from functools import reduce
print( reduce( lambda x,y:x+y, filter( lambda x:x%2==0, range(101) ) ) )
#filter(找偶数,从1-100)
#reduce(累加规则,新列表)
请使用reduce函数计算[2, 5, 7, 9]的立方和。
from functools import reduce
print(reduce(lambda x,y:x+y**3,[2,5,7,9],0))
题目:reduce实现口令保管
工作中经常需要将各种系统的口令统一保存到文件或数据库中。为了安全,保存之前需要对这些口令进行加密。
请使用 reduce 函数,按照下面规则实现一个加密程序,将用户输入的数字形式的口令进行加密。口令必须是多个数字的组合,且每个数字都在1~5之间。
编码规则(每个数字对应一个字符):
1 – s;2 – t;3 – #;4 – ^;5 – *;
例如:用户输入’134431’,会得到密文为’s#^^#s’。
请使用 reduce 编写该程序,要求用户输入一个口令,然后输出其密文形式。
(提示:reduce可以把字符串中的每一个字符处理后连接在一起,形成一个新的字符串)
from functools import reduce
d={'1': 's', '2': 't','3':'#','4':'^','5':'*'}
#字典存入键值对
pwd = input('请输入密码(1~5):')
print(reduce(lambda x,y:x+d[y],pwd,'' ))
#拼接累加用pwd作为参数
递归思想
计算一个阶乘
def 阶乘(n):
if n==1:
s=1
else:
s=n*阶乘(n-1)
return s
if __name__=='__main__':
a=阶乘(4)
print(a)
用迭代思想计算
def 迭代_阶乘(n):
s=1
for i in range(1,n+1):
s=s*i
return s
print(迭代_阶乘(5))
递归就是大事化小,小事化了
很多时候不知道要循环多少次,所以不适用迭代
比如读取子列表的子列表之类的
def 透视(s):
for i in s:
if not isinstance(i,list):
print(i)
else:
透视(i)
return
x = [5, [2, 3, ['a', 'b']], [[5, 8], [6, [9, 10]]]]
透视(x)
题目:递归求和
使用递归计算1~n的累加和
def my_add(n):
if n==1:
s=1
else:
s=n+ my_add(n-1)
return s
if __name__=='__main__':
n=int(input('请输入n的值'))
print(my_add(n))
题目:递归改写While循环
以下是一个简单的while循环,可以在屏幕上连续输出 5 个星号。请使用递归函数改写它,实现相同的功能。
n = 5
while n > 0:
print(’*’)
n -= 1
def Star(n):
if n==0:
pass
else:
print('*')
Star(n-1)
Star(5)
题目:斐波那契数列
在递归的入门练习题中,斐波那契数列是最常见的一道。它又称为黄金分割数列,形如:1,1,2,3,5,8,13…。其特点是从第三项开始,每个数字都是它之前的两个数字之和,也就是 f(n)=f(n-1)+f(n-2)。
请编写一个程序,使用递归函数,可以求出第n项的值。
def fi(n):
if n<=2:
return 1
else:
return fi(n-1)+fi(n-2)
print(fi(7))
装饰器
为了实现一个周长,面积,体积的计算,写了下面的函数
def p(r):
return 2*3.14*r
def s(r):
return 3.14*r**2
def v(r):
return 4/3*3.14*r**3
if __name__=='__main__':
print(p(5))
print(s(5))
print(v(5))
如果想要让结果都四舍五入一下
def p(r):
return round(2*3.14*r,2)
def s(r):
return round(3.14*r**2,2)
def v(r):
return round(4/3*3.14*r**3,2)
if __name__=='__main__':
print(p(5))
print(s(5))
print(v(5))
但这个round函数重复写了三次,而使用函数的初衷是想简化运算。
并且重复的三次调用,如果哪一次忘了写参数,导致精度会不一致
如果只是输出口改一下,得到下面的代码
def p(r):
return round(2*3.14*r,2)
def s(r):
return round(3.14*r**2,2)
def v(r):
return round(4/3*3.14*r**3,2)
if __name__=='__main__':
print(round(p(5),2))
print(round(s(5)),2)
print(round,v(5),2)
可以考虑使用高阶函数,所用函数随用随取
def rounded(f,r):
s=f(r)
return round(s,2)
def p(r):
return round(2*3.14*r,2)
def s(r):
return round(3.14*r**2,2)
def v(r):
return round(4/3*3.14*r**3,2)
if __name__=='__main__':
print(rounded(p,5))
print(rounded(s,5))
print(rounded(v,5))
方便批量修改
还可以进一步修改:
def rounded(f):
def a(r):
s=f(r)
return round(s,2)
return a
#函数里面定义函数
def p(r):
return 2*3.14*r
def s(r):
return 3.14*r**2
def v(r):
return 4/3*3.14*r**3
if __name__=='__main__':
p=rounded(p)
#p代表可以进行四舍五入的新函数
s=rounded(s)
v=rounded(v)
#改造出三个函数
print(p(5),s(5),v(5))
对比最上面的代码,源代码没有改动,只是添加了一部分,称为装饰器模式
主结构没变化,加了一个四舍五入功能而已
用@wraps语法糖来重写装饰器
from functools import wraps
def rounded(f):
@wraps(f)
#@是一个注解,实现声明功能的语法糖
#直接告诉Python rounded是一个装饰器
def a(r):
s=f(r)
return round(s,2)
return a
#函数里面定义函数
@rounded
def p(r):
return 2*3.14*r
@rounded
def s(r):
return 3.14*r**2
@rounded
def v(r):
return 4/3*3.14*r**3
#加了三个rounded,相当于以下三句话
''' p=rounded(p)
s=rounded(s)
v=rounded(v)'''
if __name__=='__main__':
print(p(5))
print(s(5))
print(v(5))
装饰器简单应用
标注函数调用时间
from functools import wraps
from datetime import datetime
def log(f):
@wraps(f)
def a(r):
print('函数',f.__name__,'于',datetime.now(),'被调用')
s=f(r)
return round(s,2)
return a
@log
def p(r):
return 2*3.14*r
@log
def s(r):
return 3.14*r**2
@log
def v(r):
return 4/3*3.14*r**3
#加了三个rounded,相当于以下三句话
if __name__=='__main__':
print(p(5))
print(s(5))
print(v(5))
题目:函数作为返回值
对列表排序有很多种算法。除了python自带的 sorted 之外,我们也可以自己编写各种排序方法。
以下代码定义了一个 bubble_sort 函数,就是参照“冒泡法”实现的自定义排序算法。作为测试,主程序中生成了一个包含10000个随机数的列表,并用该函数测试通过。
import random
array = [random.randint(0, 10000) for _ in range(10000)]
#冒泡排序
def bubble_sort(array):
n = len(array)
for i in range(n - 1):
for j in range(0, n - i - 1):
if array[j] > array[j + 1]:
array[j], array[j + 1] = array[j + 1], array[j]
return array
考虑到用户有时候需要用冒泡排序,有时候愿意使用python自己的sorted函数。所以请定义一个新的函数 select_func,当其参数为字符串“冒泡排序”时,返回bubble_sort函数;当参数为“内置排序”时,返回sorted函数。这样,用户在主程序中可以先调用select_func得到一个自己想要的排序函数,再用该函数执行排序。
请分别测试两种排序方法,打印排序后的列表。
import random
from functools import partial
#该包用来简化函数用法
sorted=partial(sorted,reverse=True)
#把内置函数定义为倒序排列
array = [random.randint(0, 10) for _ in range(10)]
def select_func(s):
if s=='冒泡排序':
return bubble_sort
elif s=='内置排序':
return sorted
else:
print('输入错误!')
# 冒泡排序
def bubble_sort(array):
n= len(array)
for i in range(n - 1):
for j in range(0, n - i - 1):
if array[j] > array[j + 1]:
array[j], array[j + 1] = array[j + 1], array[j]
return array
if __name__=='__main__':
my_sort=select_func(input('请输入想要采取的排序方法'))
print(array)
print(my_sort(array))
题目:函数内部定义一个函数
自定义一个函数,将前面作业中的冒泡排序算法定义在它的内部并实现逆序排序,其他功能和前面练习一样。
import random
from functools import partial
#该包用来简化函数用法
sorted=partial(sorted,reverse=True)
#创造了新的函数round2
array = [random.randint(0, 10) for _ in range(10)]
def select_func(s):
def bubble_sort(array):
n = len(array)
for i in range(n - 1):
for j in range(0, n - i - 1):
if array[j] < array[j + 1]:
array[j], array[j + 1] = array[j + 1], array[j]
return array
if s=='冒泡排序':
return bubble_sort
elif s=='内置排序':
return sorted
else:
print('输入错误!')
# 冒泡排序
if __name__=='__main__':
my_sort=select_func(input('请输入想要采取的排序方法'))
print(array)
print(my_sort(array))