python中functools.reduce、偏函数、sorted函数的理解


前言

(Python3版本)小白专用,学习心得,与大家分享一下,比较详细,不喜勿喷


一、functools.reduce()函数

1. “迭代”的理解

  1. 迭代时,当前保存的结果作为下一次循环计算的初始值

2. reduce()函数的概念

2.1语法

  1. functools.reduce (f,iterable[,initializer])
参数 性质
f 是fuction的缩写,是一个函数。规定这个函数必须有两个参数
iterable 可迭代的对象,tuple, list, dictionary, string等可迭代物,必须参数
initializer 初始值可选参数(只能给function第一个参数设置初始值,不能给第二个参数设置初始值)
  • (迭代)使用指定的带两个参数的函数f对一个数据集合(可迭代对象)的所有数据进行下列操作:使用第一个第二个数据作为参数用func()函数运算,得到的结果在与第三个数据作为参数用func()函数运算,以此类推,最后得到一个结果。

  • f为函数对象;iterable为可迭代对象;可选的initializer为初始值

代码如下(示例1:计算累加和)

import functools,operator
functools.reduce(operator.add,[1,2,3,4,5])
''' 第一个 运行结果:((((1+2)+3)+4)+5) = 15 '''

functools.reduce(operator.add,[1,2,3,4,5],10)
''' 第二个 运行结果:(((((10+1)+2)+3)+4)+5) = 15 '''

functools.reduce(operator.add,range(1,101)
''' 第三个 运行结果:(...(((((1+2)+3)+4)+5)+6)+...) = 5050 '''

温馨提示: operator模块是python内置操作符的函数接口,add是此模块中的一个具有加法功能的函数。

reduce的工作流程:

  1. 无初始值(运行过程): 例如 functools.reduce(operator.add,[1,2,3,4,5])
    第一个数据1第二个数据2作为参数用operator.add函数运算,得到的结果 3 再与第三个数据3 作为参数用operator.add函数运算,以此类推,最后得到一个结果。
  2. 有初始值(运行过程):例如 functools.reduce(operator.add,[1,2,3,4,5],10)
    第一个数据10第二个数据1作为参数用operator.add函数运算,得到的结果 11 再与第三个数据2 作为参数用operator.add函数运算,以此类推,最后得到一个结果。

代码如下(示例2:计算累乘结果)

import functools,operator
functools.reduce(operator.mul,range(1,11))

''' 运行结果:(((((((((1x2)x3)x4)x5)x6)x7)x8)x9)x10) = 3628800 '''

  • 温馨提示:range函数是 “左闭右开”, operator模块是python内置操作符的函数接口,mul是此模块中的一个具有乘法功能的函数。
  • 首先确定,functools.reduce(operator.mul,range(1,11)) 没有初始值,即运算过程同理。

2.2 reduce函数的意义

  • reduce函数使代码看起来更精简,而且运行性能更好,更准确。

二、functools.partial()偏函数

1. 偏函数的概念

  1. functools,partial()通过把一个函数的部分参数设置为默认值的方式返回一个新的可以调用的(callable)的partial 对象,其语法形式如下。

    functools.partial( func, *args, **keywords)

参数 性质
func 是fuction的缩写,是一个函数
*args *args表示任何多个无名参数,它是一个tuple(元组)
* *keywords **keywords表示关键字参数,它是一个dict(字典 :键值对)

其中,func为函数;* args为其位置参数;* * keywords为关键字参数

  • 简单理解:
    partial()函数 偏函数就是为了 固定某些参数的传入,作为默认参数(默认值)传入。
  • functools.partial (固定的函数, *args(值), **keywords(键值对))
  1. 代码如下(新建一个原函数)
import functools
def function(a,b,c,d):
	print(a,b,c,d)
function(1,2,3,4)

''' 输出结果为 1 2 3 4 '''
  • 此处是新建一个函数function,其输出结果为1234

1.1 使用 func, *args 参数的partial函数,只能是前面“连续”的参数固定

(直接继续使用原来的参数进行调用)
3. 代码如下(使用 func, *args 参数的partial函数)

import functools
def function(a,b,c,d):
	print(a,b,c,d)
fun1 = functools.partial(function,1,2)
fun1(5,6)
fun1(1,2)
''' 	输出结果为 
		1 2 5 6
		1 2 1 2 	'''
  • function函数默认值是1,2规定按顺序赋值,即a=1,b=2。所以该函数变成了function(1,2,c,d),可以理解为产生了新的函数
    fun1(5,6)调用函数function,并传入参数5和6 (用原来的参数进行函数调用),即c=5,d=6,所以最终输出结果为1256,fun1(1,2)同理。

  • 这通常只能把前面的参数固定,假如有个需求和现有的不一样,需要使后面的参数固定,该怎么做?可以使用下面的方法

1.2 使用 func, **keywords 参数的partial函数,分为两种情况

1.2.1 后面“连续”的参数固定

(直接继续使用原来的参数进行调用)

import functools
def function(a,b,c,d):
	print(a,b,c,d)
fun1 = functools.partial(function,c=4,d=2)
fun1(5,6)
fun1(1,2)
''' 	输出结果为 
		5 6 4 2
		1 2 4 2 	'''
  • 使用关键字参数(**keywords),例如此时关键字参数为 c=4,d=2,则默认参数为4和2,
    新的函数为function(a,b,4,2)
    fun1(5,6)调用函数function,并传入参数5和6 (用原来的参数进行函数调用),即a=5,b=6
    (规定默认按顺序赋值),所以最终输出结果为5642,fun1(1,2)同理。

1.2.2 非“连续”参数 或者 是直接对“前面的连续参数”赋值

(需要使用关键字参数进行调用)

import functools
def function(a,b,c,d):
	print(a,b,c,d)
fun1=functools.partial(function,c=6)
fun1(1,2,d=3)

fun2=functools.partial(function,a=6,b=3)
fun2(c=2,d=4)
''' 	输出结果为 
		1 2 6 3
		6 3 2 4 	'''
  • 对于fun1函数中给c赋值为6,参数只有一个 (即非“连续”参数) ,规定需要使用关键字参数进行调用,即参数为c=6,则新的函数为function(a,b,6,d)
    fun1(1,2,d=3)调用函数function,并传入参数1和2和d=3 (用原来的参数进行函数调用),即a=1,b=2,c=6,d=3,所以最终结果为 1263

  • 对于fun2函数中给a赋值为6,b赋值为3,参数只有两个 (即直接对前面的连续参数赋值) ,规定需要使用关键字参数进行调用,即参数为a=6,b=3,则新的函数为function(6,3,c,d)
    fun2(c=2,d=4)调用函数function,并传入参数c=2和d=4 (用原来的参数进行函数调用),即a=6,b=3,c=2,d=4,所以最终结果为 6324

1.3 偏函数的理解

  • 官方理解:

    partial()函数主要用于设置预先已知的参数,从而减少调用时传递参数的个数

  • 简单理解:
    partial()函数 偏函数就是为了 固定某些参数的传入,作为默认参数(默认值)传入。

    所以如果对参数有顺序要求的,使用偏函数要比较谨慎

1.4 举一个例子

代码如下(示例2:计算2的n次方)

import functools,math
pow2 = functools.partial(math.pow,2)	#封装pow(x,y[,z]),指定参数x=2
list(map(pow2,range(11)))	#输出2的0~10次方
''' 
运行结果:
[1.0,2.0,4.0,8.0,16.0,32.0,64.0,128.0,256.0,512.0,1024.0]
 '''

  • 温馨提示:
    1、range函数是 “左闭右开”
    2、pow是属于math模块里的函数,pow函数可以有 两个或者三个参数。pow(x,y):这个是表示x的y次幂,pow(x,y,z):这个是表示x的y次幂后除以z的余数 。
    3、map函数的原型是map(function, iterable, …),这个函数的意思就是将function应用于iterable的每一个元素,结果以列表的形式返回。

  • 首先利用偏函数讲pow函数里的参数x赋值为2,即x=2为pow的默认值。(指数为2)
    因此新的函数为pow2 = pow(2,y)
    最后用map函数调用pow2函数对1至10范围内数字进行迭代。(指数为2,幂从1~10)
    最终的输出的结果是被list()强制转化为列表类型。


三、sorted()函数

1. sorted()函数的概念

  1. 内置函数sorted()把一个可迭代对象进行排序,返回结果列表,其语法形式如下。

    sorted( iterable,*,key = None, reverse = False)

参数 性质
iterable 可迭代类型,例如字典、列表…
key = None 可迭代类型中某个属性,对给定元素的每一项进行排序
reverse = False 降序或升序
  • iterable为待排序的可迭代对象
    key = None为其比较函数(默认None,按自然顺序排序)
    reverse = False为指定是否逆序排序
  • 单独一个星号(*)不是参数,它是一个“分割符号”,它的作用是“告诉大家,调用函数时传入排在它(*)后面的参数,都要带名字(类似键值对)”

2. 对数值进行排序

2.1 只有一个参数(iterable)时

  1. 代码如下(sorted()函数示例)
numbers = [1,6,4,-2,9] 
print(sorted(numbers))	#按数值自然排序
''' 输出结果为 [-2,1,4,6,9] '''

print(numbers)
''' 输出结果为 [1,6,4,-2,9] '''

  • 由运行结果可知:
    1.sorted()函数不需要定义。它是一个内置函数,可以在标准的Python安装中使用。

    2.在没有额外的参数的情况下,sorted()函数按照升序对值进行排列,也就是按照从小到大的顺序。

    3.原始的numbers不会改变,因为sorted()函数提供了一个新的有序的输出结果,并且不改变原始值的顺序。
    4.当sorted()函数被调用时,它会提供一个有序的列表作为返回值

最后一点意味着列表可以使用sorted()函数,并且输出结果可以立刻赋值给一个变量:

numbers = [1,6,4,-2,9] 
number_sorted = sorted(numbers)	#按数值自然排序
print(number_sorted)

''' 输出结果为 [-2,1,4,6,9] '''
  • 在这个例子中,有一个新的变量numbers_sorted存储了sorted()函数的输出结果。

2.2 有参数reverse = False时

  • sorted()函数有一个可选的参数reverse,它将根据分配给它的布尔值改变排序。如果reverse = True,那么就会按照降序排列;如果reverse = False或者没有参数reverse,那么就会按照升序排列
numbers = [1,6,4,-2,9] 
number_sorted = sorted(numbers,reverse = True)	#按数值逆序排序
print(number_sorted)

''' 输出结果为 [9,6,4,1,-2] '''

2.3 有参数key = None时

numbers = [1,6,4,-2,9] 
number_sorted = sorted(numbers,key = abs)	 #按绝对值排序
print(number_sorted)

''' 输出结果为 [1,-2,4,6,9] '''

温馨提示:abs()函数返回给定参数的绝对值,参数可以是实数(整数、浮点数等)或复数,
如果参数是复数,则返回复数的模。

  • 在排序过程中,将对每个元素调用key函数来确定排序顺序,但不会改变原来的数值
    numbers中用绝对值可理解为,按照[1,6,4,-2,9] 的绝对值 [ 1,6,4,2,9 ] 来升序排序
    (无reverse参数,默认reverse = False,不逆序,即默认升序排序)

  • 又因为key函数只是用来确定排序顺序,并不会改变原有的值
    所以输出结果为[1,-2,4,6,9],而不是[1,2,4,6,9]

  • 当使用带有参数key的函数时,有两个主要限制

1、传递给key的比较函数(该函数只能带1个参数)
(例如定义一个函数名为add(x,y),用于加法功能的函数。在排序过程中每次调用add()函数,它每次只从列表中接收一个元素)key=add是错误的,因为add()函数有两个参数

2、带有key的函数必须能够处理迭代序列中的所有值
(详细请看链接: 请点击这里.)

3. 对字符串进行排序

3.1 当你对字符串排序时,大小写很重要

  • 列表中字符串首字母均是大写 或者 小写的时候,默认 按26字母表排序,若第一个字母相同,就看第二个,以此类推。
  • 列表中的字符串字母 即有大写字母开头的字符串,又有小写字母开头的字符串,则按照Unicode数值来从小到大排序
str1 = ["Dog","Cat","Rabbit"] #首字母均是大写
str2 = ["Dog","cat","Rabbit"] #cat首字母是小写
str3 = ["Dog","cat","Rabbit"] #cat首字母是小写

str1_sorted = sorted(str1)	 #按26字母表顺序排序
str2_sorted = sorted(str2)	 #按照Unicode数值来排序
str3_sorted = sorted(str3,key=str.lower)	#按26字母表顺序排序
print(str1_sorted)
print(str2_sorted)
print(str3_sorted)

''' 输出结果为 
['Cat','Dog','Rabbit']
['Dog','Rabbit','cat']
['Cat','Dog','Rabbit']
 '''

温馨提示:lower()方法是Python字符串方法。它将字符串中所有大写字母转换为小写字母,并返回一个新字符串。

  • str1中的三个字符串首字母都是大写,所以按照26字母表排序。
  • str2中的cat中的c是小写,Dog和Rabbit中首字母是大写,因此有大小写。即按照字母在Unicode中所对应的数值排序。Unicode码分别对应的数值 D:68 、R:82 、c:99
    因此排序为 Dog,Rabbit,cat
  • str3中元素与str2相同,但是 比较函数 key = str.lower,意味着将str3中的元素全部当成 小写字母 来比较。虽然str3中的既有大写又有小写,但排序方式是按小写字母排序的,即26字母表排序。因此输出结果为 [‘Cat’,‘Dog’,‘Rabbit’]

3.2 按字符串长度排序

代码如下

str_1 = ["Dog","cat","Rabbit"] #cat首字母是小写
str_1_sorted = sorted(str_1,key = len) #按字符串长度排序
print(str_1_sorted)

'''输出结果:
['Dog','cat','Rabbit']
'''
  • 因为key=len,所以对str_1函数是用长度进行排序的,默认从小到大。
  • 字符串若长度相同,则按字典排序。 D:68、c:99
    所以输出结果为 [‘Dog’,‘cat’,‘Rabbit’]

3.3 按元组的元素排序

  • 默认按元组的第一个元素排序
  • 若要按第二个或者第三等等,则需要修改 比较函数 key
    代码如下
tuple1 = [('Bob',75),('Adam',92),('Lisa',88)] 
tuple2 = [('Bob',75),('Adam',92),('Lisa',88)]  
tuple1_sorted = sorted(tuple1)  #默认按第一个元素排序
tuple2_sorted = sorted(tuple2,key = lambda t:t[1]) #按元组的第二个元素排序
print(tuple1_sorted)
print(tuple2_sorted)

'''输出结果:
[('Adam',92),('Bob',75),('Lisa',88)] 

[('Bob',75),('Lisa',88),('Adam',92)] 
'''

温馨提示:lambda 函数的语法只包含一个语句,表现形式如下:

  • lambda [arg1 [,arg2,…argn]]:expression
    其中,lambda 是 Python 预留的关键字,[arg…] 和 expression 由用户自定义。
    [arg…] 是参数列表,它的结构与 Python 中函数(function)的参数列表是一样的。[arg…] 可以有非常多的形式。
    expression 是一个参数表达式,表达式中出现的参数需要在[arg…]中有定义,并且表达式只能是单行的,只能有一个表达式。
    例如:f = lambda x,y:x+y 中f为函数,x,y为两个参数, x+y为函数返回值

  • tuple1_sorted函数中的参数没有key,则默认按第一个元素排序。
    由于每个元组中第一个元素都是大写字母,所以排序是按26字母顺序表排序。
    即A,B,L 所以输出结果为 [(‘Adam’,92),(‘Bob’,75),(‘Lisa’,88)]

  • tuple2_sorted函数中有参数 key,key = lambda t:t[1] ,
    此处的lambda匿名函数的作用是 按第二个元素 进行排序,
    即75,88,92所以输出结果为 [(‘Bob’,75),(‘Lisa’,88),(‘Adam’,92)]

4. 如果您还不懂 或者 想详细了解sorted函数,请点击下方链接。

链接: 请点击这里.


总结

python中 functools.reduce函数、偏函数(functools.partial)、sorted函数的理解

  • 1、functools.reduce (f,iterable[,initializer]) 函数就是 将第一个参数(函数)对 第二个参数对象进行迭代运算。
    2、partial()函数 偏函数就是为了 固定某些参数的传入,作为默认参数(默认值)传入。
    3、内置函数sorted()把一个可迭代对象进行排序,返回结果列表

猜你喜欢

转载自blog.csdn.net/m0_51284422/article/details/109166809