首页 > 编程语言 >Python 2-04 匿名函数

Python 2-04 匿名函数

时间:2023-05-22 11:06:21浏览次数:35  
标签:sort 04 Python 列表 匿名 key sorted 排序 lambda


Python 匿名函数

一、匿名函数 lambda λ

lambda [args]: expression 即 lambda [参数列表]: 表达式
lambda_add = lambda x, y: x + y

def normal_add(x,y):
    return x+y       

assert lambda_add(2,3) == normal_add(2,3)

注:assert expression [, arguments] 即: assert 表达式 [, 参数] 如果断言成功,返回空;如果断言失败,assert 语句本身就会抛出 AssertionError。启动 Python 解释器时可以用 -O 参数来关闭 assert

关键字 lambda 表示匿名函数,冒号前面的 x,y 表示函数参数列表,x+y 是执行代码。
匿名函数只能有一个表达式,表达式的结果就是其返回值,没有 return 语句。

二、lambda 与命名函数

1、lambda 匿名

def 有函数名,而 lambda 没有,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量:

>>> lambda x: x * x
<function <lambda> at 0x00000000004A6160>
>>> f = lambda x: x * x
>>> f(6)
36

2、lambda 是一个表达式,而 def 则是一个语句。

lambda 函数拥有自己的命名空间

x, y = 1, 2
f = lambda x: x + y
print(x, f(3)) # 1 5

lambda 作为一个表达式,可出现在一个列表、函数调用的参数,也可以把匿名函数作为别的函数的返回值返回。

# 纯属为了理解 lambda 没有实际含义
def f(foo):
    x=foo(1)
    print(x)
    return lambda y:y+x

print(f(lambda x:2*x)(3))

3、参数带默认值

sum_with_100 = lambda x, y=100: x + y
# 等同于:
def sum_with_100(x, y=100): 
    return x + y

print(sum_with_100(200))

4、从后面传参

之前的示例我们将 lambda 匿名函数赋值一个变量,通过类似 def 定义的函数的方式传参,我们可以在 lambda 后面直接传递参数:

two_sum = (lambda x, y: x + y)(3, 4)
print(two_sum)

三、lambda 应用

1、把下面的函数改为匿名函数:

def is_odd(n):
    return n % 2 == 1

2、结合三元表达式求两值中最小值

lower = lambda x,y: x if x<y else y 
print(lower(7,100))

3、对字典某一键值进行排序

d = [{"order":3},{"order":1},{"order":2}]
# 根据order键值排序
d.sort(key=lambda x:x['order']) 
print(d)

四、排序指南

Python 列表有一个内置的 list.sort() 方法可以直接修改列表。还有一个 sorted() 内置函数,它会从一个可迭代对象构建一个新的排序列表。

1、基本排序

简单的升序排序非常简单:只需调用 sorted() 函数即可。它会返回一个新的已排序列表。

>>> sorted([5, 2, 3, 1, 4])
[1, 2, 3, 4, 5]

你也可以使用 list.sort() 方法,它会直接修改原列表(并返回 None 以避免混淆),通常来说它不如 sorted() 方便 ——— 但如果你不需要原列表,它会更有效率。

>>> a = [5, 2, 3, 1, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5]

另外一个区别是, list.sort() 方法只是为列表定义的,而 sorted() 函数可以接受任何可迭代对象。

>>> sorted({1: 'D', 2: 'B', 3: 'B', 4: 'E', 5: 'A'})
[1, 2, 3, 4, 5]

2、关键函数

list.sort() 和 sorted() 都有一个 key 形参来指定在进行比较之前要在每个列表元素上进行调用的函数。

例如,下面是一个不区分大小写的字符串比较:

>>> sorted("This is a test string from Andrew".split(), key=str.lower)
['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']

key 形参的值应该是一个函数,它接受一个参数并返回一个用于排序的键。这种技巧速度很快,因为对于每个输入记录只会调用一次 key 函数。

Python 程序中,key = str.lower 是什么意思?

key = str.lower 是一个函数,返回字符串(转换为小写字符)的拷贝。

一种常见的模式是使用对象的一些索引作为键对复杂对象进行排序。例如:

>>> student_tuples = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
>>> sorted(student_tuples, key=lambda student: student[2])   # sort by age
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

同样的技术也适用于具有命名属性的对象。例如:

>>> class Student:
...     def __init__(self, name, grade, age):
...         self.name = name
...         self.grade = grade
...         self.age = age

...     def __repr__(self):
...         return repr((self.name, self.grade, self.age))

>>> student_objects = [Student('john', 'A', 15), Student('jane', 'B', 12),Student('dave', 'B', 10)]

>>> sorted(student_objects, key=lambda student: student.age)   # sort by age
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

3、Operator 模块函数

上面显示的键函数模式非常常见,因此 Python 提供了便利功能,使访问器功能更容易,更快捷。 operator 模块有 itemgetter() 、 attrgetter() 和 methodcaller() 函数。

使用这些函数,上述示例变得更简单,更快捷:

>>> from operator import itemgetter, attrgetter

>>> sorted(student_tuples, key=itemgetter(2))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

>>> sorted(student_objects, key=attrgetter('age'))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

Operator 模块功能允许多级排序。 例如,按 grade 排序,然后按 age 排序:

>>> sorted(student_tuples, key=itemgetter(1,2))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]

>>> sorted(student_objects, key=attrgetter('grade', 'age'))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]

4、升序和降序

list.sort() 和 sorted() 接受布尔值的 reverse 参数。这用于标记降序排序。 例如,要以反向 age 顺序获取学生数据:

>>> sorted(student_tuples, key=itemgetter(2), reverse=True)
[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]

>>> sorted(student_objects, key=attrgetter('age'), reverse=True)
[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]

5、排序稳定性和排序复杂度

排序保证是 稳定 的。 这意味着当多个记录具有相同的键值时,将保留其原始顺序。

>>> data = [('red', 1), ('blue', 1), ('red', 2), ('blue', 2)]

>>> sorted(data, key=itemgetter(0))
[('blue', 1), ('blue', 2), ('red', 1), ('red', 2)]

注意 blue 的两个记录如何保留它们的原始顺序,以便 (‘blue’, 1) 保证在 (‘blue’, 2) 之前。

这个美妙的属性允许你在一系列排序步骤中构建复杂的排序。例如,要按 grade 降序然后 age 升序对学生数据进行排序,请先 age 排序,然后再使用 grade 排序:

>>> s = sorted(student_objects, key=attrgetter('age'))     # sort on secondary key

>>> sorted(s, key=attrgetter('grade'), reverse=True)       # now sort on primary key, descending
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

6、sort() 与 sorted()

列表额外提供了以下方法:

sort(*, key=None, reverse=False)

此方法会对列表进行原地排序,只使用 < 来进行各项间比较。 异常不会被屏蔽 —— 如果有任何比较操作失败,整个排序操作将失败(而列表可能会处于被部分修改的状态)。

sort() 接受两个仅限以关键字形式传入的参数 (仅限关键字参数):

key 指定带有一个参数的函数,用于从每个列表元素中提取比较键 (例如 key=str.lower)。 对应于列表中每一项的键会被计算一次,然后在整个排序过程中使用。 默认值 None 表示直接对列表项排序而不计算一个单独的键值。

reverse 为一个布尔值。 如果设为 True,则每个列表元素将按反向顺序比较进行排序。

当顺序大尺寸序列时此方法会原地修改该序列以保证空间经济性。 为提醒用户此操作是通过间接影响进行的,它并不会返回排序后的序列(请使用 sorted() 显示地请求一个新的已排序列表实例)。

sort() 方法确保是稳定的。 如果一个排序确保不会改变比较结果相等的元素的相对顺序就称其为稳定的 — 这有利于进行多重排序(例如先按部门、再接薪级排序)。

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

根据 iterable 中的项返回一个新的已排序列表。具有两个可选参数,它们都必须指定为关键字参数。

key 指定带有单个参数的函数,用于从 iterable 的每个元素中提取用于比较的键 (例如 key=str.lower)。 默认值为 None (直接比较元素)。

reverse 为一个布尔值。 如果设为 True,则每个列表元素将按反向顺序比较进行排序。

内置的 sorted() 确保是稳定的。 如果一个排序确保不会改变比较结果相等的元素的相对顺序就称其为稳定的 — 这有利于进行多重排序(例如先按部门、再按薪级排序)。

练习

模块设计允许用户输入10个单词,然后依字母顺序排列,并显示它们。

def words_function():
    words = [input("Enter 10 words, one at a time: ") for i in range(10)]
    sorted(words, key=str.lower)
    print("Alphabetized, your words are: ", words)

    userSearch = input("What word would you like to search for?")

    if userSearch in words:
        print("Found!")
    else:
        print("Not Found!")  

words_function()

结果不对,问题出在那里?

s = 'I have a module designed to allow users to enter 10 words, then alphabetize them, and display them. '
l = l1 = l2 = l3 = s.split()
print(l.sort(),l)
print(l1.sort(key=str.lower),l1)
print(sorted(l2))
print(sorted(l3,key=str.lower))

List sort() 方法

sort() 函数用于对原列表进行排序,如果指定参数,则使用比较函数指定的比较函数。

list.sort( key=None, reverse=False)
# key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
# reverse -- 排序规则,reverse = True 降序, reverse = False 升序(默认)。

该方法没有返回值,但是会对列表的对象进行排序。

aList = ['Google', 'Runoob', 'Taobao', 'Facebook']
aList.sort()
print ( "List : ", aList)

以下实例降序输出列表:

vowels = ['e', 'a', 'u', 'o', 'i']
# 降序
vowels.sort(reverse=True)
# 输出结果
print ( '降序输出:', vowels )

以下实例演示了通过指定列表中的元素排序来输出列表:

# 获取列表的第二个元素
def takeSecond(elem):
    return elem[1]
# 列表
lst = [(2, 2), (3, 4), (4, 1), (1, 3)]
# 指定第二个元素排序
lst.sort(key=takeSecond)
# 输出类别
print ('排序列表:', lst)

以上实例输出结果如下:
排序列表:[(4, 1), (2, 2), (1, 3), (3, 4)]

Python3 sorted() 内置函数

orted() 函数对所有可迭代的对象进行排序操作。

sorted(iterable, key=None, reverse=False)  
# iterable -- 可迭代对象。
# key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
# reverse -- 排序规则,reverse = True 降序 , reverse = False 升序(默认)。

返回重新排序的列表。

>>>sorted([5, 2, 3, 1, 4])
[1, 2, 3, 4, 5] # 默认为升序
你也可以使用 list 的 list.sort() 方法。这个方法会修改原始的 list(返回值为None)。通常这个方法不如sorted()方便-如果你不需要原始的 list,list.sort()方法效率会稍微高一些。

>>> a=[5,2,3,1,4]
>>> a.sort()
>>> a
[1,2,3,4,5]
另一个区别在于list.sort() 方法只为 list 定义。而 sorted() 函数可以接收任何的 iterable。

>>> sorted({1: 'D', 2: 'B', 3: 'B', 4: 'E', 5: 'A'})
[1, 2, 3, 4, 5]

利用 key 进行倒序排序

>>> example_list = [5, 0, 6, 1, 2, 7, 3, 4]
>>> result_list = sorted(example_list, key=lambda x: x*-1)
>>> print(result_list) [7, 6, 5, 4, 3, 2, 1, 0]

要进行反向排序,也通过传入第三个参数 reverse=True:

>>>example_list = [5, 0, 6, 1, 2, 7, 3, 4] 
>>> sorted(example_list, reverse=True) 
[7, 6, 5, 4, 3, 2, 1, 0]

sorted 的应用,也可以通过 key 的值来进行数组/字典的排序,比如:

array = [{"age":20,"name":"a"},{"age":25,"name":"b"},{"age":10,"name":"c"}]
array = sorted(array,key=lambda x:x["age"])
print(array)

输出结果:
[{‘age’: 10, ‘name’: ‘c’}, {‘age’: 20, ‘name’: ‘a’}, {‘age’: 25, ‘name’: ‘b’}]

多列排序

先按照成绩降序排序,相同成绩的按照名字升序排序:

d1 = [{'name':'alice', 'score':38}, {'name':'bob', 'score':18}, {'name':'darl', 'score':28}, {'name':'christ', 'score':28}]
l = sorted(d1, key=lambda x:(-x['score'], x['name']))
print(l)

输出结果:
[{‘name’: ‘alice’, ‘score’: 38}, {‘name’: ‘christ’, ‘score’: 28}, {‘name’: ‘darl’, ‘score’: 28}, {‘name’: ‘bob’, ‘score’: 18}]

sort 与 sorted 区别:

sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。

list 的 sort 方法返回的是对已经存在的列表进行操作,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。


标签:sort,04,Python,列表,匿名,key,sorted,排序,lambda
From: https://blog.51cto.com/u_1439909/6321613

相关文章

  • Python 1-14 列表
    Python1-14列表一、Python列表Python的列表是一个有序可重复的元素集合classlist([iterable])虽然被称为函数,list实际上是一种可变序列类型。1、创建创建一个列表,在方括号括中用逗号分隔不同的数据项。列表内的元素,可以是其它任意类型的数据,可多层嵌套列表,元素个数无限制。>>......
  • Python 1-14 列表
    Python1-14列表一、Python列表Python的列表是一个有序可重复的元素集合classlist([iterable])虽然被称为函数,list实际上是一种可变序列类型。1、创建创建一个列表,在方括号括中用逗号分隔不同的数据项。列表内的元素,可以是其它任意类型的数据,可多层嵌套列表,元素个数无限制。>>......
  • Python 2-03 递推和递归
    递推和递归一、递推算法Recursionmethod递推算法是通过已知条件,利用特定关系得出中间推论,直至得到结果的算法。递推算法分为顺推和逆推两种。动态规划1、顺推法所谓顺推法是从已知条件出发,逐步推算出要解决的问题的方法叫顺推。#n!阶乘deffactorial(n):t=1fori......
  • Python 2-07 装饰器 @decorator
    Python装饰器@decoratorPython装饰器其实就是对函数的包装,函数作为参数,在不修改函数源代码的基础上,并对函数做一些包装,然后返回增加了包装的函数,即生成了一个新函数。登录校验,权限校验,日志记录等,这些功能在各个环节都可能需要,但又十分雷同,可以通过装饰器来抽象、剥离这部分代码......
  • Python 4-09 time
    time 在 Python 中与时间处理有关的模块包括 time,datetime 以及 calendar。在 Python 中,用三种方式来表示时间,分别是时间戳、格式化时间字符串和结构化时间。时间戳(timestamp):1970年1月1日之后的秒,可以通过 time.time() 获得。时间戳是一个浮点数,可以进行加减运算,但......
  • Python 1-18 字典
    Python1-18字典Python的字典数据类型采用键值对(key:value)的形式,根据key的值计算value的地址,具有非常快的查取和插入速度。例如,用list实现成绩单:#给定一个名字,要查找对应的成绩,就先要在names中找到对应的位置,再从scores取出对应的成绩,list越长,耗时越长。names=......
  • Python 1-17 元组
    Python1-17元组classtuple([iterable])tuple是一个不可变的序列类型。>>>s='abc'>>>l=[1,2]>>>t=1,2>>>d=dict(a=1,b=2)>>>set={'a','b'}1、元组创建>>>tup=()#创建空元组>>......
  • Python 2-02 命名空间和作用域
    命名空间和作用域一、命名空间命名空间(Namespace)是从名称到对象的映射,一般用Python字典来实现。为了解决项目中名字冲突的问题引入了命名空间的概念,命名空间可以嵌套。1、命名空间分类:内置名称(built-innames),Python语言内置的名称,比如函数名abs、char和异常名称Exception......
  • Python 2-01 函数
    一、函数定义def函数名(参数列表):函数体判断一个数是不是素数?#方法一:for循环判断素数num=int(input('请输入一个正整数:'))foriinrange(2,int(num**0.5)+1):ifnotnum%i:print(f'{num}不是素数')breakelse: print(f'{num}是素数')......
  • Python 2-06 闭包
    闭包Closures嵌套函数(nestedfunction),内函数引用了外函数的临时变量,并且外函数返回内函数的引用,这样就构成了一个闭包。defouter():x,y,z=10,'abc',[1,2]definner():print(x,y)returninnerf=outer()print(f.__closure__)#celltuple......