1. 匿名函数

匿名函数适用于简单的业务处理,可以快速并简单的创建函数

匿名函数受限于 函数体只能写一行 ,所有匿名函数只能处理非常简单的功能

  • 传统的函数的定义包括了:函数名 + 函数体
def send_email():
    pass


# 1. 执行
send_email()
# 2. 当做列表元素
data_list = [send_email, send_email, send_email]
# 3. 当做参数传递
other_function(send_email)
  • 匿名函数,则是基于lambda表达式实现定义一个可以没有名字的函数,例如:
data_list = [ lambda x:x+100,  lambda x:x+110, lambda x:x+120 ]
print(data_list[0] )
print(data_list[0](2132))
  • 基于Lambda定义的函数格式为:lambda 参数:函数体
    • 参数,支持任意参数
lambda x: 函数体
lambda x1,x2: 函数体
lambda *args, **kwargs: 函数体
  • 函数体,只能支持单行的代码,默认将函数体单行代码执行的结果返回给函数的执行者
def func(x):
    return x + 100
# 等同于
func = lambda x: x + 100

2. 三元运算

简单的函数,可以基于lambda表达式实现

简单的条件语句,可以基于三元运算实现,例如:

num_list = [1,2,3,4,5]
if 6 in num_list:
    data = True
else:
    data = False

# 等同于
num_list = [1,2,3,4,5]
data = True if 6 in num_list else False  # 结果 = 条件成立时  if  条件 else 不成立

通过三元运算编写匿名函数时,可以处理再稍微复杂点的情况,例如:

func = lambda x: True if x.isdecimal() else False
"""
def func(x):
    if x.isdecimal():
        return True
    else:
        return False
"""


func = lambda text: text.split('.')[-1] if type(text) == str else ''
"""
def func(text):
    if type(text) == str:
        return text.split('.')[-1]
    else:
        return ''
"""

3. 生成器

生成器是由函数+yield关键字创造出来的写法,在特定情况下,用它可以帮助我们节省内存。

  • 生成器函数:函数中有yield存在时,这个函数就是生产生成器函数
  • 生成器对象:执行生成器函数时,会返回一个生成器对象
  • 生成器的特点:记录在函数中的执行位置,下次执行next时,会从上一次的位置基础上再继续向下执行
# 执行生成器函数func,返回的生成器对象
# 注意:执行生成器函数时,函数内部代码不会执行

def func():
    for index, item in enumerate(['a', 'b', 'c', 'd'], 1):
        print(index)
        yield item


data = func()  # 执行生成器函数时,函数内部代码不会执行

v1 = next(data)  # print(1)
print(v1)  # 执行到yield就不在执行,返回第一个yield的值"a"
v2 = next(data)  # print(2)
print(v2)  # 2   # 从上一次中止的yield后面执行,不再从头执行,返回第二个yield值"b"

应用场景

假设要让你生成 300w个随机的4位数,并打印出来。

  • 传统方式:在内存中一次性创建300w个
  • 生成器方式:动态创建,用一个创建一个
import random


def get_random_num(max_count):
    for _ in range(max_count):
        yield random.randint(1000, 9999)


random_num_list = get_random_num(3000000)

for index, item in enumerate(random_num_list, 1):
    print(index, item)

4. 内置函数

内置函数
abs() divmod() input() open() staticmethod()
all() enumerate() int() ord() str()
any() eval() isinstance() pow() sum()
basestring() execfile() issubclass() print() super()
bin() file() iter() property() tuple()
bool() filter() len() range() type()
bytearray() float() list() raw_input() unichr()
callable() format() locals() reduce() unicode()
chr() frozenset() long() reload() vars()
classmethod() getattr() map() repr() xrange()
cmp() globals() max() reverse() zip()
compile() hasattr() memoryview() round() import()
complex() hash() min() set() dir()
delattr() help() next() setattr() id()
dict() hex() object() slice() oct()
sorted()
  • range:生成一个数字列表
v1 = range(5)  # [0,1,2,3,4]
v2 = range(5, 10)  # [5,6,7,8,9]
v3 = range(5, 10, 2)  # [5,7,9]
v4 = range(10, 0, -1)  # [10,9,8,7,...,1]
  • abs:绝对值
print(abs(-10))
  • pow:指数
# 计算 3 的 3 次方: 3 ** 3 = 27
print(pow(3, 3))


# 对 3 * 3 = 27 进行 10 的余数运算: 27 % 10 = 7
print(pow(3, 3, 10))
  • sum:求和
# 可迭代对象
print(sum([-11, 22, 33]))  # 44
  • divmod:求商和余数
# 执行整数除法 9 // 2,商为 4,余数为 1
print(divmod(9, 2))  # 输出 (4, 1)

# 将 divmod 的结果分别赋值给 v1 和 v2
v1, v2 = divmod(9, 2)  # v1=4 v2=1
  • round:小数点后n位(四舍五入)
print(round(3.1415, 3))  # 3.142
  • minmax :最小值、最大值
# 语法: max(iterable, *[, key, default])
# iterable: 可迭代对象
# default: 用来指定最大值不存在时返回的默认值。
# key: 传入一个函数,它的作用就是决定要按什么东西去比较大小

data_list = [-11, -22, 33, 44, -55]
data_dict = [
    {'id': 20, 'age': 29},
    {'id': 9, 'age': 9},
    {'id': 11, 'age': 139}
]

# max() 函数示例
print(max((), default=1))  # 1

# 对整数列表的 max() 示例
print(min(data_list), max(data_list))  # -55 44
print(min(data_list, key=lambda num: abs(num)))  # -11
print(max(data_list, key=lambda num: num * 10))  # 44

# 对字典列表的 max() 示例
print(min(data_dict, key=lambda x: x['id']))  # {'id': 9, 'age': 9}
print(max(data_dict, key=lambda x: x['age']))  # {'id': 11, 'age': 139}
  • all:是否全部为True
  • any:是否存在True
print(all([11, 22, 44, ""]))  # False
print(any([11,22,44,""])) # True
  • binocthex

    • bin:十进制转二进制
    • oct:十进制转八进制
    • hex:十进制转十六进制
  • ord:获取字符对应的unicode码点(十进制)

str1 = ord("嘿")
print(str1, hex(str1)) # 22079 # 再用hex转换为16进制 0x563f
  • chr:根据码点(十进制)获取对应字符
print(chr(22079)) # 嘿
  • encodedecodebytes
v1 = '小明'  # str类型

v2 = v1.encode('utf-8')  # str 转 bytes
print(v2)  # b'\xe5\xb0\x8f\xe6\x98\x8e'

v3 = v2.decode('utf-8')  # bytes 转 str
print(v3)  # 小明

v4 = bytes(v1, encoding='utf-8')  # 直接将 str 转 bytes
print(v4)  # b'\xe5\xb0\x8f\xe6\x98\x8e'

# 注意:bytes 和 encode 的效果相同
  • enumerate  :循环输出数据,并为每个数据维护一个数值
my_list = ['a','b','c']

for item in enumerate(my_list):
    print(item)  # 获得的值为带数值的元组
# (0, 'a')
# (1, 'b')
# (2, 'c')


for k,v in enumerate(my_list,10): # 从10开始计数
    print(k,v)   # 使用解构将元组拆分为index和value
# 10 a
# 11 b
# 12 c
  • hash :将数据返回一个hash值
print(hash("嘿嘿"))
  • zip:拉链函数,将相同位置的元素提取出来,组成一个新的元组,直到没有相同位置则不再取
v1 = [11, 22, 33, 44, 55, 66]
v2 = [55, 66, 77, 88]
v3 = [10, 20, 30, 40, 50]

result = zip(v1, v2, v3)
for item in result:
    print(item)
"""
(11, 55, 10)
(22, 66, 20)
.....
"""
  • callable:判断是否可执行(后面是否可以加括号)
v1 = "小明"
v2 = lambda x: x
def v3():
    pass

print(callable(v1)) # False
print(callable(v2))
print(callable(v3))
  • sorted:排序
sorted(iterable[,key][,reverse])

# iterable:是可迭代类型类型;
# key:用列表元素的某个属性和函数进行作为关键字,有默认值,迭代集合中的一项;
# reverse:排序规则. reverse = True 或者 reverse = False,有默认值。
info = {
    "root": {
        'id': 20,
        'age': 29
    },
    "seven": {
        'id': 9,
        'age': 9
    },
    "admin": {
        'id': 11,
        'age': 139
    },
}
result = sorted(info.items(), key=lambda x: x[1]['id'])  # info.items(),返回的是一个元组('root', {'id': 20, 'age': 29})
print(result)  # [('seven', {'id': 9, 'age': 9}), ('admin', {'id': 11, 'age': 139}), ('root', {'id': 20, 'age': 29})]
data_list = [
    '1-5 xxx.jpg',
    '1-17 xxx.jpg',
    '1-9 xxx.jpg',
    '1-16 xxx.jpg'
]

result = sorted(data_list,key=lambda x: int(x.split(" ")[0].split('-')[-1]))
print(result)  # ['1-5 xxx', '1-9 xxx', '1-16 xxx', '1-17 xxx']
# 多级排序,先根据value,value相同再根据key进行排序

d = {2: 'D', 6: 'B', 3: 'B', 5: 'E', 4: 'A'}
d_sort = {k: v for k, v in sorted(d.items(), key=lambda x: (x[1], x[0]))}

print(d_sort)
# [(4, 'A'), (3, 'B'), (6, 'B'), (2, 'D'), (5, 'E')]
  • map:接受两个参数:函数和可迭代对象,并返回一个迭代器
"""
map(func, *iterables)  
- func: 可执行的函数
- iterables:迭代器,可迭代的序列
"""


# 定义一个函数,用于计算一个数的立方
def cube(num):
    return num ** 3


# 创建一个包含数字的列表
num_list = [i for i in range(1, 6)]

# 使用普通 for 循环计算立方并打印
for item in num_list:
    print(cube(item))

# 使用 map 返回一个迭代器,计算每个数字的立方并打印
iter_data = map(cube, num_list)
print(next(iter_data))  # 打印第一个立方值
for item in iter_data:
    print(item)
# 四舍五入一个可迭代对象中每个值
num_list = [1.22334, 5.524234, 9.33423, 8.6565]
iter_data = map(round, num_list)
print(next(iter_data))
for i in iter_data:
    print(i)

5. 推导式

  • 列表 (集合与列表一样,只是 '[]' 与 '{}'的区别)
num_list = [i for i in range(1, 5)]  # [1, 2, 3, 4]

num_list = [[i, i] for i in range(5) if i > 2]  # [[3, 3],[4, 4]]

num_list = [i + 100 for i in range(5) if i > 2]  # [103, 104]

num_list = ["user-{}".format(i) for i in range(5) if i > 2]  # ['user-3', 'user-4']
  • 字典
num_list = {i: i for i in range(1, 5)}  # {1: 1, 2: 2, 3: 3, 4: 4}

num_list = {i: (i + 100) for i in range(5) if i > 2}  # {3: 103, 4: 104}

num_list = {"user-{}".format(i): i for i in range(5) if i > 2}  # {'user-3': 3, 'user-4': 4}
  • 元组
    • 不会立即执行内部循环去生成数据,而是得到一个生成器(yield)
data = (i for i in range(10))

print(data)  # <generator object <genexpr> at 0x000001A99BFDE7C8>
print(next(data))  # 0
print(next(data))  # 1

for item in data:
    print(item)
# 2
# 3
# ...

5.1 推导式练习题

  1. 去除列表中每个元素的.jpg后缀
data_list = [
    '1-5 xxx.jpg',
    '1-17 xxx.jpg',
    '1-9 xxx.jpg',
    '1-16 xxx.jpg',
]

result = [item.split('.')[0] for item in data_list]  # 去掉 .jpg 后缀
print(result)  # ['1-5 xxx', '1-17 xxx', '1-9 xxx', '1-16 xxx']
  1. 将字典中的元素按 k-v 格式化,并最终使用 ;连接起来
info = {
    "name": "小明",
    "email": "xxx@live.com",
    "gender": "男",
}

result = ";".join(["{}-{}".format(k, v) for k, v in info.items()])  # name-小明;email-xxx@live.com;gender-男
  1. 将字典按照键从小到大排序,然后在按照如下格式拼接起来。(微信支付API内部处理需求)
# 最终输出 out_refund_no=12323&refund_fee=10000&sign_type=MD5&total_fee=9901

info = {
    'sign_type': "MD5",
    'out_refund_no': "12323",
    'total_fee': 9901,
    'refund_fee': 10000
}

result = "&".join(["{}={}".format(k,v) for k,v in sorted(info.items(), key=lambda x: x[0])])


"""
import urllib.parse
result2 = urllib.parse.urlencode(info)
print(result2)
"""
  1. 看代码写结果
def func():
    print(123)

data_list = [func for i in range(10)]

print(data_list) # 10个func函数的地址
  1. 看代码写结果
def func(num):
    return num + 100

data_list = [func(i) for i in range(5)]
print(data_list)   # [100, 101, 102, 103, 104]
  1. 看代码写结果
def func(x):
    return x + i   # func()函数中的i与推导式不在一个作用域,i未定义

data_list = [func for i in range(10)] # i=9 推导式内部也会维护一个作用域

val = data_list[0](100)
print(val) # i没有定义
  1. 看代码写结果 (新浪微博面试题)
data_list = [lambda x: x + i for i in range(10)]  # [函数,函数,函数]   i=9
v1 = data_list[0](100)
v2 = data_list[3](100)
print(v1, v2)  # 109 109

5.2 推导式扩展题

  • 推导式支持嵌套
data_list = [ [i,j] for i in range(3) for j in range(i+1)]  # [[0, 0], [1, 0], [1, 1], [2, 0], [2, 1], [2, 2]]
  1. 利用推导式 生成一副扑克牌
# 生成一副扑克牌
poker_list = [ "{}{}".format(color,num) for color in ['红桃','黑桃','方片','梅花'] for num in range(1,14)]
  1. 分析代码
def num():
    return [lambda x: i * x for i in range(4)] # [lambda x: 3*x, ....]


# 1. num()并获取返回值  [函数,函数,函数,函数] i=3
# 2. for循环返回值
# 3. 返回值的每个元素(2)
result = [m(2) for m in num()]  # [6,6,6,6]
print(result)

6. 练习题

  1. 看代码写结果
v = [lambda: x for x in range(10)]
print(v)  # 9个函数为元素的列表
print(v[0])  # lambda :9 函数的地址
print(v[0]())  # 9
  1. 看代码写结果
v = [i for i in range(10, 0, -1) if i > 5]  # 10 9 8 7 6
  1. 看代码写结果
data = [lambda x: x * i for i in range(10)]  # i=9
print(data)  # [lambda x:x*9....] 9个
print(data[0](2))  # 18
print(data[0](2) == data[8](2))  # True
  1. 利用推导式剔除列表中的字符串并生成新的列表
data_list = [11, 2, 33, 'hello', 456, 'root']
new_list = [item for item in data_list if type(item) != str]
print(new_list)
  1. 请用列表推导式实现,对data_list中的每个元素判断,如果是字符串类型,则计算长度作为元素放在新列表的元素中;如果是整型,则让其值+100 作为元素放在新的列表的元素中
data_list = [11, 2, 33, 'hello', 456, 'root']

# 利用三元运算+推导式
new_list = [len(item) if type(item) == str else item + 100 for item in data_list]
  1. 利用字典推导式实现,将如下列表构造成指定格式的字典
data_list = [
    (1, '小明', 19),
    (2, '小红', 84),
    (3, '小王', 73)
]

# 请使用推导式将data_list构造生如下格式
"""
result = {
    1: (1, '小明', 19),
    2: (2, '小红', 84),
    3: (3, '小王', 73)}
}
"""

result = {item[0]: item for item in data_list}
print(result)
  1. 对比字典中每个人的牌的大小,并输入牌最大的人的姓名
player = {
    "小明": ["红桃", 10],
    "小红": ["红桃", 8],
    'eric': ["黑桃", 3],
    'killy': ["梅花", 12],
}

print((sorted(player.items(), key=lambda x: x[1][1], reverse=True))[0][0])
  1. 请编写一个生成器函数实现生成n个斐波那契数列的值
  • 什么是斐波那契数列?
前两个数相加的结果,就是下一个数。
1 1 2 3 5 8 13 21 34 55 ...
  • 代码
def fib(count):
    first, second = 0, 1
    for i in range(count):
        first, second = second, first + second
        yield first


count = int(input("请输入生成斐波那契数列的个数: "))
fib_generator = fib(count)
for num in fib_generator:
    print(num)
posted on 2023-10-20 16:48  龙泉寺老方丈  阅读(11)  评论(0编辑  收藏  举报