python函数高级话题
python函数高级话题
递归函数
递归是颇为高级的话题,它在Python中相对少见。然而,它是一项应该了解的有用的技术,因为它允许程序遍历拥有任意的、不可预知的形状的结构。递归甚至是简单循环和迭代的替换,尽管它不一定是最简单的或最高效的一种。
用递归求和
让我们来看一些例子。
要对一个数字列表(或者其他序列)求和,我们可以使用内置的sum函数,或者自己编写一个更加定制化的版本。这里是用递归编写的一个定制求和函数的示例:
def mysum(L):
#print(L)
if not L:
return 0
else:
return L[0]+mysum(L[1:])#调用自身
print(mysum([1,2,3,4,5,6]))
Fibonacci公式:
公式:f(x)=f(x-1)+f(x-2)
举例说明:
list=[]
n=int(input("请输入:"))#因为input输出的是str类型,所以需要强转
def sums(n):
if n==1:
return 1
if n==2:
return 1
else:
return sums(n-1)+sums(n-2)
for i in range(1,n+1):
list.append(sums(i))
print(list)
在每一层,这个函数都递归地调用自己来计算列表剩余的值的和,这个和随后加到前面的一项中。当列表变为空的时候,递归循环结束并返回0。当像这样使用递归的时候,对函数调用的每一个打开的层级,在运行时调用堆栈上都有自己的一个函数本地作用域的副本,也就是说,这意味着L在每个层级都是不同的。如上注释部分的print(L),可以运行查看结果。
正如你所看到的,在每个递归层级上,要加和的列表变得越来越小,直到它变为空——递归循环结束。加和随着递归调用的展开而计算出来。
匿名函数:lambda
lambda表达式
lambda的一般形式是关键字lambda,之后是一个或多个参数(与一个def头部内用括号括起来的参数列表极其相似),紧跟的是一个冒号,之后是一个表达式,即:
lambda para1, para2, ..…, paraN : expression using paras
由lambda表达式所返回的函数对象与由def创建并赋值后的函数对象工作起来是完全一样的,但是1ambda有一些不同之处让其在扮演特定的角色时很有用。
- lambda是一个表达式,而不是一个语句。因为这一点,lambda能够出现在Python语法不允许def出现的地方——例如,在一个列表常量中或者函数调用的参数中。此外,作为一个表达式,lambda返回了一个值(一个新的函数),可以选择性地赋值给一个变量名。相反,def语句总是得在头部将一个新的函数赋值给一个变量名,而不是将这个函数作为结果返回。
- lambda的主体是一个单个的表达式,而不是一个代码块。这个lambda的主体简单得就好像放在def主体的return语句中的代码一样。简单地将结果写成一个顺畅的表达式,而不是明确的返回。因为它仅限于表达式,lambda通常要比def功能要小:你仅能够在lambda主体中封装有限的逻辑进去,连if这样的语句都不能够使用。这是有意设计的——它限制了程序的嵌套:lambda是一个为编写简单的函数而设计的,而def用来处理更大的任务。
除了这些差别,def和lambda都能够做同样种类的工作,例如:
def add(x,y,z):
return x+y+z
print(add(1,2,3))
#结果:6
利用lambda写的例子:
add = lambda x,y,z:x+y+z
print(add(1,2,3))
#结果:6
这里的add被赋值给一个lambda表达式创建的函数对象,这里就是def所完成的任务,只不过def的赋值是自动进行的。
默认参数也能够在lambda参数中使用,就像在def中使用一样。
f=(lambda a='tom',b='loves',c='python':a+b+c)
print(f())
print(f('lilei'))
print(f('lucy','likes','to travel'))
以上运行结果:
tomlovespython
lileilovespython
lucylikesto travel
高阶函数
高阶函数:把一个函数名,以实参的形式,传给这个函数的形参,这个函数就称为高阶函数。
比如下面的形参c,对应的实参是一个函数名abs.
def add(a,b,c):
return c(a)+c(b)
add_value=add(-9,1,abs)
print(add_value)
#运行结果:10
最正确的高阶函数解释
满足下面两个条件之一,就可称之为高阶函数:
-
1.把一个函数名当做一个实参,传给另外一个函数
-
2.返回值中包含函数名(不修改函数的调用方式)
示例1:
import time
def bar():
time.sleep(1)
print("函数bar")
def test1(func):#高阶函数(满足了条件)
start_time=time.time()
func()
stop_time=time.time()
print("这个函数的运行时间是%s"%(stop_time-start_time))
test1(bar)
#结果:函数bar
# 这个函数的运行时间是1.0007131099700928
示例2:
import time
def bar():#高阶函数(满足了条件)
time.sleep(1)
print("in the bar")
def test2(func):
print(func)
return func
bar=test2(bar)
bar()
#运行结果:<function bar at 0x0000021FC3C71E18>
# in the bar
python 中常见的高阶函数
(1)filter
-
功能
- filter的功能是过滤掉序列中不符合函数条件的元素,当序列中要删减的元素可以用某些函数描述时,就应该想起filter函数。
-
调用
- filter(function,sequence),function是条件,sequence是序列
- function可以是匿名函数或者自定义函数,它会对后面的sequence序列的每个元素判定是否符合函数条件,返回TRUE或者FALSE,从而只留下TRUE的元素;sequence可以是列表,元组或者字符串。
- filter(function,sequence),function是条件,sequence是序列
例子1:
x=[1,2,3,4,5]
y=filter(lambda x:x%2==0,x)#找出偶数
print(y)
#结果:<filter object at 0x000002B97F1F7128> #过滤后的对象
print(list(y))#py3之后filter函数返回的不再是列表而是迭代器,所以需要用list转换
#结果:[2, 4]
例子2:
#普通函数使用lambda
x=[1,2,3,4,5]
def is_odd(n):
return n%2==1 #找出所有的奇数
print(list(filter(is_odd,x)))#过滤后的对象转为列表形式输出
#结果:[1, 3, 5]
(2)map
-
功能
- 求一个序列或者多个序列进行函数映射之后的值,就该想到map这个函数,它是python自带的函数,py3返回的是迭代器,同filter,需要进行列表转换
-
调用
-
map(function.iterable1,iterable2),
- function中的参数值不一定是一个x,也可以是x和y,甚至多个,后面的iterable表示需要参与function运算中的参数值,有几个参数值就传入几个iterable
-
例子1:
x=[1,2,3,4,5]
y=[2,3,4,5,6]
z=map(lambda x,y:(x*y)+2,x,y)
print(z)
#结果:<map object at 0x000001594F007198>
print(list(z))
#结果:[4, 8, 14, 22, 32]
例子2:
#普通函数:
def func(x,y):
return x*y+2
x=[1,2,3,4,5]
y=[2,3,4,5,6]
print(list(map(func,x,y)))
#结果:[4, 8, 14, 22, 32]
例子3:
#传入3参数也是一样的
def func(x,y,z):
return x*y+z
x=[1,2,3,4,5]
z=y=[2,3,4,5,6]
print(list(map(func,x,y,z)))
注:map中如果传入的几个序列的长度不一,那么会依据最短的序列进行计算
(3)reduce
-
功能
- 对一个序列进行压缩运算,得到一个值,但是reduce在python2的时候是内置函数,到了python3移到了functools模块,所以使用之前需要 from functools import reduce
-
调用
- reduce(function ,iterable)
- 其中function必须传入两个参数,iterable可以是列表或者元组
例子:
from functools import reduce
y=[2,3,4,5,6]
z=reduce(lambda x,y:x+y,y)
print(z)
#结果:20
例子2:
#普通函数:
from functools import reduce
def tools(x,y):
return x+y
y=[2,3,4,5,6]
print(reduce(tools,y,100))
其计算原理:
先计算头两个元素:f(2, 3),结果为5;
再把结果和第3个元素计算:f(5, 4),结果为9;
再把结果和第4个元素计算:f(9, 5),结果为14;
再把结果和第5个元素计算:f(14, 6),结果为20;
由于没有更多的元素了,计算结束,返回结果20。
(4)apply
-
功能
- 是pandas中的函数,应用对象为pandas中的DataFrame或者Series.大致有两个方面的功能:一是直接对DataFrame或者Series应用函数,二是对pandas中的groupby之后的聚合对象apply函数
-
调用
-
apply(function,axis),function表明所使用的函数,axis表明对行或者列做运算。
安装才能使用apply函数
-
#在cmd命令窗口安装
pip install numpy
pip install pandas
#画图
pip install matplotlib
画图使用先导包:
import matplotlib.pyplot as plt
>>> x=[4,7,11,21]
>>> plt.plot(x)
[<matplotlib.lines.Line2D object at 0x000001F66180BDD8>]
>>> plt.show()
>>>
例子:
>>> import numpy as np
>>> import pandas as pd
>>> a=np.random.randint(low=0,high=4,size=(2,4))
>>> a
array([[0, 2, 2, 0],
[1, 2, 2, 1]])
>>> data=pd.DataFrame(a)
>>> data
0 1 2 3
0 0 2 2 0
1 1 2 2 1
>>> data.apply(lambda x:x*10)
0 1 2 3
0 0 20 20 0
1 10 20 20 10
>>>
(5)zip
-
功能
-
zip()函数用于将可迭代对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象。
如果各个可迭代对象的元素个数不一致,则返回的对象长度与最短的可迭代对象相同。
利用*号操作符,与zip相反,进行解压。
-
-
调用
-
zip(iterable1,iterable2,…)
-
iterable 一个或多个可迭代对象(字符串、列表、元组、字典)
python2中直接返回一个由元组组成的列表,python3中返回的是一个对象,如果想要得到列表,可以用list()函数进行转换。
-
例子:
x=[2,3,4,5,6]
y=[4,5,6,7,8]
print(list(zip(x,y)))
#结果:[(2, 4), (3, 5), (4, 6), (5, 7), (6, 8)]
例子2:
a=[1,2,3]#此处可迭代对象为列表
b=[4,5,6]
c=[5,6,7,8,9]
zipTest=zip(a,b)
# <zip object at 0x00000115C0C87288>返回的是一个对象
print(zipTest)
print(list(zipTest))#转为列表
#结果:[(1, 4), (2, 5), (3, 6)]
zipT=zip(a,c)
print(list(zip(*zipT)))#解压也使用list进行转换
#结果:[(1, 2, 3), (5, 6, 7)]
例子3:
a={1:11,2:22}#此处可迭代对象为字典
b={3:33,4:44}
c={5:55,6:66,7:77}
ziptest=zip(a,b,c)
print(list(ziptest))
zipt=zip(a,b)
print(list(zip(*zipt)))
题目:
1.利使用map()函数,把使用户输入的不规范的英文名字,变为首字母大写,其余小写的规范名字。输入:[hunan, YINGXIAO, COllege],输出:[Hunan, Yingxiao, College]
2.回文数是指从左向右读和从右向左读都是一样的数,例如12321,909。请利使用filter()挑选出1-1000里的回文数:
解析:
①.第一题
def formatation(seq):
return seq[0].upper()+seq[1:].lower()
sr=['hunan','CHANGSHA','collage']
print(list(map(formatation,sr)))
#运行结果:
#['Hunan', 'Changsha', 'Collage']
②.第二题
def palindrome(n):
rev_n=int(str(n)[::-1])
if rev_n==n:
return rev_n
print(list(filter(palindrome,range(1,1000))))
#运行结果:[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99, 101, 111, 121, 131, 141, 151, 161, 171, 181, 191, 202, 212, 222, 232, 242, 252, 262, 272, 282, 292, 303, 313, 323, 333, 343, 353, 363, 373, 383, 393, 404, 414, 424, 434, 444, 454, 464, 474, 484, 494, 505, 515, 525, 535, 545, 555, 565, 575, 585, 595, 606, 616, 626, 636, 646, 656, 666, 676, 686, 696, 707, 717, 727, 737, 747, 757, 767, 777, 787, 797, 808, 818, 828, 838, 848, 858, 868, 878, 888, 898, 909, 919, 929, 939, 949, 959, 969, 979, 989, 999]
本文深入探讨Python中的高级函数话题,包括递归函数的概念和示例,如用递归求和及Fibonacci公式;讲解lambda表达式的使用,阐述其与def的区别;详细解析高阶函数,如filter、map、reduce和zip的应用场景和实例。通过这些内容,提升对Python函数理解的深度。

34万+

被折叠的 条评论
为什么被折叠?



