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
min
、max
:最小值、最大值
# 语法: 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
:是否全部为Trueany
:是否存在True
print(all([11, 22, 44, ""])) # False
print(any([11,22,44,""])) # True
-
bin
、oct
、hex
bin
:十进制转二进制oct
:十进制转八进制hex
:十进制转十六进制
-
ord
:获取字符对应的unicode码点(十进制)
str1 = ord("嘿")
print(str1, hex(str1)) # 22079 # 再用hex转换为16进制 0x563f
chr
:根据码点(十进制)获取对应字符
print(chr(22079)) # 嘿
encode
、decode
、bytes
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 推导式练习题
- 去除列表中每个元素的.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']
- 将字典中的元素按
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-男
- 将字典按照键从小到大排序,然后在按照如下格式拼接起来。(微信支付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)
"""
- 看代码写结果
def func():
print(123)
data_list = [func for i in range(10)]
print(data_list) # 10个func函数的地址
- 看代码写结果
def func(num):
return num + 100
data_list = [func(i) for i in range(5)]
print(data_list) # [100, 101, 102, 103, 104]
- 看代码写结果
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没有定义
- 看代码写结果 (新浪微博面试题)
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]]
- 利用推导式 生成一副扑克牌
# 生成一副扑克牌
poker_list = [ "{}{}".format(color,num) for color in ['红桃','黑桃','方片','梅花'] for num in range(1,14)]
- 分析代码
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. 练习题
- 看代码写结果
v = [lambda: x for x in range(10)]
print(v) # 9个函数为元素的列表
print(v[0]) # lambda :9 函数的地址
print(v[0]()) # 9
- 看代码写结果
v = [i for i in range(10, 0, -1) if i > 5] # 10 9 8 7 6
- 看代码写结果
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
- 利用推导式剔除列表中的字符串并生成新的列表
data_list = [11, 2, 33, 'hello', 456, 'root']
new_list = [item for item in data_list if type(item) != str]
print(new_list)
- 请用列表推导式实现,对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]
- 利用字典推导式实现,将如下列表构造成指定格式的字典
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)
- 对比字典中每个人的牌的大小,并输入牌最大的人的姓名
player = {
"小明": ["红桃", 10],
"小红": ["红桃", 8],
'eric': ["黑桃", 3],
'killy': ["梅花", 12],
}
print((sorted(player.items(), key=lambda x: x[1][1], reverse=True))[0][0])
- 请编写一个生成器函数实现生成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)