十七、三元表达式和匿名函数

本文详细介绍了Python中的三元表达式、多种生成式(列表生成式、字典生成式、集合生成式)以及匿名函数的使用,包括其语法和实际应用。同时,讲解了内置函数如max、min、map、filter、reduce和zip的用法,并给出了相关练习。此外,还探讨了多层装饰器和有参装饰器的执行流程。
摘要由CSDN通过智能技术生成

一 三元表达式

语法: 条件为真返回的值 if 条件 else 条件为假返回的值

def get_max1(a, b):
    if a > b:
        return a
    else:
        return b


def get_max2(a, b):
    return a if a > b else b


print(get_max1(1, 2))  # 2
print(get_max2(1, 2))  # 2

上面两个函数实现的功能是完全一样的,下面使用的就是三元表达式,可以看出,代码更加的简洁,而且可读性也不会变差。

二 多种生成式

2.1 列表生成式

语法:[表达式 for 变量名 in 可迭代对象 if 条件 ] if可加可不加

# 需求:生成一个1到10中2的倍数的列表
res = [i for i in range(2, 11, 2)]
print(res)  # [2, 4, 6, 8, 10]

res1 = [x * y for x in [1, 2, 3] for y in [4, 5, 6]]  # 相当于循环嵌套
print(res1)  # [4, 5, 6, 8, 10, 12, 12, 15, 18]

my_list = ['jasper', 'jack', 'jason']
# 需求:给my_list的每个数据都加上_NB
# 方式一:
new_list = []
for i in my_list:
    # new_list.append(i + '_NB')
    new_list.append(''.join([i, '_NB']))
print(new_list)  # ['jasper_NB', 'jack_NB', 'jason_NB']

# 方式二:用列表生成式
new_list1 = [''.join([i, '_NB']) for i in my_list]
print(new_list1)  # ['jasper_NB', 'jack_NB', 'jason_NB']


new_list2 = [''.join([i, '_NB']) for i in my_list if i != 'jasper']
print(new_list2)  # ['jack_NB', 'jason_NB']
# 支持if判断 for循环出来的数据 先进行判断 条件成立则交给左边的表达式 条件不成立则不交给表达式

列表生成式可以包含for和if,但是不包含其他的。

2.2 字典生成式

语法:{k:v for k in 可迭代对象 for v in 可迭代对象}

# 字典生成式
res = {k: v for k in range(3) for v in ['jasper', 'lili', 'jack']}
print(res)  # {0: 'jack', 1: 'jack', 2: 'jack'}


my_dict = {'name': 'jasper', 'age': 18, 'hobby': 'read'}
# 需求:将字典里的k,v互换
new_dict = {v: k for k, v in my_dict.items()}
print(new_dict)  # {'jasper': 'name', 18: 'age', 'read': 'hobby'}

2.3 集合生成式

语法:{表达式 for 变量名 in 可迭代对象} 可以加if条件判断,集合里for循环的数据必须是不可变类型。

# 集合生成式
my_set = {i for i in range(10) if i != 4}
print(my_set, type(my_set))  # {0, 1, 2, 3, 5, 6, 7, 8, 9} <class 'set'>

python中没有元组生成式

nt_know = (i for i in range(5))
print(my_dont_know)  # <generator object <genexpr> at 0x0000014ABFFA07B0>
# 是一个生成器对象

三 匿名函数

3.1 简介

匿名函数就是没有函数名的函数,它主要用在需要一个函数,但实现的功能很简单,而且只需要使用一次,这时就可以使用匿名函数。

3.2 语法

关键字lambda 形参: 返回值

# 匿名函数
lambda a, b: a * b

# 调用方式一:
# 将整个匿名函数括起来后面直接加括号调用
res = (lambda a, b: a * b)(3, 4)
print(res)  # 12

# 调用方式二:
# 将匿名函数赋值给一个变量名使用变量名加括号调用
func = lambda a, b: a * b
print(func(3, 4))  # 12

说明:使用lambda表达式时,可以有多个参数,之间用逗号隔开,表达式只能有一个,只能返回一个值,不支持for和while等。

3.3 实际应用

# # 匿名函数
# lambda a, b: a * b
#
# # 调用方式一:
# # 将整个匿名函数括起来后面直接加括号调用
res = (lambda a, b: a * b)(3, 4)
print(res)  # 12
#
# # 调用方式二:
# # 将匿名函数赋值给一个变量名使用变量名加括号调用
func = lambda a, b: a * b
print(func(3, 4))  # 12


# 需求:编写一个计算圆的面积的函数
import math


def get_area(r):
    return math.pi * r ** 2


print(get_area(3))  # 28.274333882308138


# 使用匿名函数
print((lambda r: math.pi * r ** 2)(3))  # 28.274333882308138

匿名函数一般和内置函数结合使用,可以减少代码的书写量。

# 匿名函数和内置函数结合使用
my_dict = {
    'fish': 100,
    'pig': 200,
    'beef': 300
}
# 求字典中value的最大值
res1 = max(my_dict)
print(res1)  # pig 找到的是字典中最大的key
res2 = max(my_dict, key=lambda k: my_dict.get(k))
print(res2)  # beef

四 内置函数

4.1 重要内置函数

max()

求最大值
max函数如果只提供了一个位置参数,必须是一个非空的可迭代对象,返回可迭代对象中最大的元素,如果提供两个或两个以上的位置参数,则返回最大的位置参数。

# max(iterable, *[, default=obj, key=func]) -> value
# max(arg1, arg2, *args, *[, key=func]) -> value

print(max([i for i in range(4)]))  # 3
print(max(3, 5, 7, 9, 2))  # 9
print(max('j', 'z', 'A'))  # z

min()

求最小值
和max函数相反

#  min(iterable, *[, default=obj, key=func]) -> value
#  min(arg1, arg2, *args, *[, key=func]) -> value

print(min([i for i in range(4)]))  # 0
print(min(3, 5, 7, 9, 2))  # 2
print(min('j', 'z', 'A'))  # A

map()

映射
第一个参数传一个函数,可以是内置的也可以是自定义的,后面可以传多个可迭代对象,返回一个迭代器对象,可用list()转换。
这个函数的意思就是将可迭代对象里的每个元素应用到函数中

list1 = [1, 'name', 3, 4]
tuple1 = (6, 7, 8, 9)
str1 = 'hello'
print(map(str, list1))  # <map object at 0x0000018D6C5D5FA0>
print(list(map(str, list1)))  # ['1', 'name', '3', '4']
print(list(map(str, tuple1)))  # ['1', 'name', '3', '4']
print(list(map(str, str1)))  # ['h', 'e', 'l', 'l', 'o']
# 将可迭代对象的每个数据都转成字符串

# 使用自定义参数
def func(x, y, z):
    return x, y, z


list2 = [1, 2, 3]
list3 = [4, 5, 6]
list4 = [4, 5, 6, 7, 8, 9]
print(list(map(func, list2, list3, list4)))  # [(1, 4, 4), (2, 5, 5), (3, 6, 6)]
# 如果长度不一致 结果取决于最短的那个

filter()

过滤
用于过滤序列,过滤掉不符合条件的数据,返回一个迭代器对象,可用list()转换。
两个参数,参数1是函数,参数2是序列,将序列里的每一个元素作为参数传入函数进行判断,返回True或False,
将结果为True的放到新的列表中。

l1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]


# 去除掉l1的所有奇数
def func(n):
    return n % 2 == 0


print(list(filter(func, l1)))  # [2, 4, 6, 8]


# 使用匿名函数
res = filter(lambda n: n % 2 == 0, l1)
print(list(res))  # [2, 4, 6, 8]

reduce()

求和
reduce在python2中是一个内置函数,但是在python3中被移植到functools模块中。
两个参数:第1个是函数名,第二个是队列。
reduce函数先从队列或列表中取出两个元素,执行函数,得到的结果作为一个元素,在从左至右依次取出一个元素,执行函数,直到队列所有的元素被取完。返回的是一个数据值

from functools import reduce

l2 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
# 求列表中所有数的和

# 方式一
print(sum(l2))  # 45

# 方式二
print(reduce(lambda x, y: x + y, l2))  # 45

zip()

拉链
可以接受多个可迭代对象,然后将每个可迭代对象的第n个元素结合在一起,返回一个元组类型的迭代器,可用list()转换。

l1 = [1, 2, 3, 4]
dic = {
    'name': 'jasper',
    'age': 19,
    'gander': 'male',
    'hobby': 'read',
}
str1 = 'jack'

print(list(zip(l1, dic, str1)))
# # [(1, 'name', 'j'), (2, 'age', 'a'), (3, 'gander', 'c'), (4, 'hobby', 'k')]

如果长度不统一,决定结果的还是最短的那个。

4.2 常见内置函数

在这里插入图片描述

4.2.1 数据类型

# 数据类型相关
int()
float()
str()
list()
dict()
tuple()
bool()
set()
complex()  # 复数

4.2.2 进制转换

# 进制转换
print(bin(100))  # 0b1100100 十转二
print(oct(100))  # 0o144  十转八
print(hex(100))  # 0x64  十转十六
int()  # 其他进制转十进制

4.2.3 数学运算

# 数学运算
print(abs(-6))  # 6 求绝对值
print(pow(2, 3, 3))  # 2**3 % 3  a的b幂次方在和c取余
print(divmod(66, 3))  # (22, 0) 返回商和余数
print(round(99.6))  # 100 返回四舍五入
sum()  # 求和
max()  # 求最大
min()  # 求最小

4.2.4 和作用域有关

# 和作用域有关
print(globals())  # 查看全局名称空间的名字
print(locals())  # 要在局部空间使用 此时结果和全局一致

4.2.5 输入输出

# 输入输出
input()
print()

4.2.6 文件相关

# 文件相关
open()

4.2.7 其他

all()  # 所有未True才返回True
any()  # 有一个未True就返回True


bytes('你', encoding='utf8')  # b'\xe4\xbd\xa0' 将字符串转为二进制


callable()  # 用于检查一个对象是否可调用
chr() 
ord()  # 根据ASC表实现数字和字符之间的转换


dir()  # 查看内置属性


enumerate({1, 2, 3, 4})
#  <enumerate object at 0x000001C183873540>  [(0, 1), (1, 2), (2, 3), (3, 4)] 获取集合的枚举对象
evar() 
exec()  # 能够识别字符串中的代码并执行


format()  # 格式化


help()  # 打印帮助信息
hash()  # 获取对象的哈希值


id()  # 查看内存地址
isinstance(1, int)  # True  判断数据类型 返回布尔值


len()  # 返回一个对象中元素个数


reversed([1, 2, 3, 4, 5])  # reversed([1, 2, 3, 4, 5])
# 将一个序列反转 返回一个迭代器
range()  # 生成数据


sorted()  # 对可迭代对象进行排序


type()  # 判断数据类型

练习

多层装饰器及有参装饰器的执行流程用文字具体描述出来

  1. 多层装饰器
    函数test上面叠加了三个装饰器,从下至上依次是outer1,outer2,outer3,执行流程是,先将函数名test传入outer1的形参func_name1,此时func_name1是真正的test,返回inner1。将inner1传入中间的装饰器outer2,此时outer2中func_name2是inner1,返回inner2。将inner2传入最上面的装饰器outer3,此时outer3中的func_name3是inner2,返回inner3。因为outer3是最后一个装饰器,所以将inner3赋值给全局的变量名test,此时全局的test已经不是被装饰之前的test,而是inner3的内存地址,test(),调用test。其实是执行inner3,inner3中的func_name3为inner2,接着执行inner2,此时func_name2为inner1,接着执行inner1,而inner1才是真正的test,执行真正的test,return,接着inner2,inner3也依次结束。
  2. 有参装饰器
    装饰器内部需要一个参数用于当作条件或者数据值,此时就需要给函数体传参。给函数体传参的方式有两种,第一种通过形参传入,但装饰器外层函数的形参是用来接收被装饰对象的,内层函数的形参是用来接收被装饰对象的参数的,都不能修改,所以只能用闭包函数传参,定义一个函数将装饰器包起来,形参中可传多个参数,在原装饰器同层返回原装饰器名,此时有参装饰器就完成了。执行流程是,被装饰对象上有一个@外层函数(参数),函数名加括号先执行外层函数,流程为将参数传入外层函数,定义一个原装饰器函数名放到外层函数的局部空间,返回原装饰器函数名,此时就变形为@原装饰器函数名,执行流程就和无参装饰器一致,此时函数体内部就可以访问到添加的参数。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值