函数式编程
NOTE
使用纯函数(相同的输入总是产生相同的输出,没有副作用)
避免可变状态和数据变化
函数是一等公民(可以像变量一样传递)
强调递归而非循环
但是我想说,它是能让你的 py
脚本更简洁。类似于 javscript
推出了一系列的数组方法,在处理数据和格式化方面及其方便。不用在自己傻傻的 for
循环了。
开始之前,你应当回顾数据类型转换的问题。
list()、dict() 类型转换
要明确一点,list
和 dict
是试图将可迭代对象变更为字典和列表类型。 在 Python
的原生类型中可迭代对象类型如下:
list, tuple, str, dict, set, renge 函数, 文件对象
字典的转换默认会得到所有的 key
,如果想获取 value
则需要使用 dict.values()
py
# 字典转 ...
dic = { "a": 1, "b": 2, "c": 3 }
print(list(dic)) # ['a', 'b', 'c']
print(tuple(dic)) # ('a', 'b', 'c')
print(str(dic)) # "{'a': 1, 'b': 2, 'c': 3}"
print(set(dic)) # {'a', 'c', 'b'}
# 列表转 ...
array = [1, 2, 3, 4, 5]
print(dict(array)) # ❌
print(tuple(array)) # (1, 2, 3, 4, 5)
print(set(array)) # {1, 2, 3, 4, 5}
print(str(array)) # "[1, 2, 3, 4, 5]"
# 字符串转 ...
string = "hello"
print(list(string)) # ['h', 'e', 'l', 'l', 'o']
print(set(string)) # {'h', 'e', 'l', 'o'} 列表
print(tuple(string)) # ('h', 'e', 'l', 'l, 'o')
print(dict(string)) # ❌
# 集合转 ...
set1 = {'h', 'e', 'l', 'o'}
print(list(set1)) # ['h', 'e', 'l', 'o']
print(str(set1)) # "{'h', 'e', 'l', 'o'}"
print(tuple(set1)) # ('h', 'e', 'l', 'o')
print(dict(set1)) # ❌
# 元组转 ...
tuple1 = ('h', 'e', 'l', 'o')
print(list(tuple1)) # ['h', 'e', 'l', 'o']
print(str(tuple1)) # "('h', 'e', 'l', 'o
print(set(tuple1)) # {'h', 'e', 'l', 'o'}
print(dict(tuple1)) # ❌
想要转字典的前提是这是一个二维结构,可以有任意数据结构组合排除 set。比如
py
list_val = [[1, 2], [3, 4]]
tuple_val = ((1, 2), [3, 4])
print(dict(list_val), dict(tuple_val))
表达式
在 py
中,简单来说只要是一行能够解决的问题,都叫表达式。像数学运算、条件运算、逻辑运算、三元运算、lambda
、生成式。
数学、逻辑、条件、三元运算
py
# 数学运算
result = a + b
# 条件运算 返回比对的结果 True or False
result = a < b
# 逻辑运算
# 如果 a 存在返回 a,反之返回 b
result = a or b
# 如果 a 和 b 都存在才会返回 True
result = a and b
# 三元运算
result = '正确' if a < b else '错误'
# 可以允许相对复杂的运算,不建议使用,可读性差
result = '优秀' if a >= 90 else '还行' if a >= 80 else '不行'
# 等价于
if a >= 90:
result = '优秀'
elif a >= 80:
result = '还行'
else:
result = '不行'
生成式
py
# 列表生成式
numbers = [1, 2, 3, 4, 5]
squared = [x ** 2 for x in numbers]
# 带条件的列表生成式
even_squared = [x ** 2 for x in numbers if x % 2 == 0]
# 字典生成式
keys = ['a', 'b', 'c']
values = [1, 2, 3]
mapping = {k: v for k, v in zip(keys, values)}
print(mapping) # {'a': 1, 'b': 2, 'c': 3}
# 带条件的字典生成式
even_squares = {x: x**2 for x in numbers if x % 2 == 0}
print(even_squares) # {2: 4, 4: 16}
# 集合生成式
numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
unique_squares = {x**2 for x in numbers}
print(unique_squares) # {16, 1, 9, 4} (顺序可能不同)
# 带条件的集合生成式
even_squares = {x**2 for x in numbers if x % 2 == 0}
print(even_squares) # {16, 4}
# 生成器表达式 使用 () 返回的是一个生成器,需要手动转数据类型。
# 数据量比较大时,使用此方式提高执行速度
# 基本语法:(表达式 for 项目 in 可迭代对象)
numbers = [1, 2, 3, 4, 5]
squared_gen = (x**2 for x in numbers)
print(squared_gen) # <generator object <genexpr> at 0x...>
lambda 匿名函数
这是一种简洁的定义函数的方式,一行代码定义简单的函数,不需要命名,特别适合一次性使用的函数。 lambda [参数]: 函数体
lambda
后只能跟表达式
py
# 无参数
greet = lambda: 'hello world'
print(greet()) # hello world
# 带参数, 一个或多个和 def 函数一样
get_count = lambda x, y: x + y
print(get_count(1, 2)) # 3
# 默认参数
get_diff = lambda x, y=[2, 4]: [i for i in x if i not in y]
print(get_diff([1, 2, 3, 4])) # Output: [1, 3]
# 可变参数
sum_all = lambda *args: sum(args)
print(sum_all(1, 2, 3, 4)) # 10
# 关键字参数
create_person = lambda **kwargs: kwargs
print(create_person(name="alice", age=25)) # { 'name': 'alice', 'age': 25 }
# 立即调用
result = (lambda x, y: x * y)(1, 2) # 2
数据格式化方法
经常用到方法有很多,大致可以分为两类,像 map
filter
zip
reversed
返回的是一个可迭代对象,必须通过 list
等类型转换方法进行进行。
map
常用于基于一个可迭代对象,生成另一个新的可迭代对象。
py
list_val = [1, 2, 3, 4, 5]
list(map(lambda item: item % 2 == 0, list_val))
filter
常用于基于一个可迭代对象,过滤出来一个新的可迭代对象
py
list_val = [1, 2, 3, 4, 5]
list(filter(lambda item: item % 2 ===0, list_val))
reduce
对一个可迭代对象做累计操作,第一个参数是
py
from functools import reduce
list_val = [1, 2, 3, 4, 5]
print(reduce(lambda x, y: x + y, list_val)) # 15
zip
将两个可迭代对象进行合并,以短的为准
py
list_val = [1, 2, 3, 4, 5]
list_val1 = [6, 7, 8, 9, 10, 11]
print(list(zip(list_val, list_val1)), dict(zip(list_val, list_val1)))
# [(1, 6), (2, 7), (3, 8), (4, 9), (5, 10)]
# {1: 6, 2: 7, 3: 8, 4: 9, 5: 10}
# 解压缩, 解压时只能对列表进行操作
first, second = zip(*list(zip(list_val, list_val1)))
reversed
翻转可迭代对象
py
dic = { 'a': 1, 'b': 2, 'c': 3}
print(list(reversed(dic))) # ['c', 'b', 'a']
any、all
py
list_val = [1, 2, 3, 4, 5]
# any 任何元素为 True 就返回 True
print(any(list(map(lambda item: item >= 3, list_val)))) # True
# all 全部元素为 True 才返回 True
print(all(list(map(lambda item: item >= 3, list_val)))) # False
数学及排序方法
py
print(sum([1, 2, 3])) # 6
print(max([1, 2, 3])) # 3
print(min([1, 2, 3])) # 1
print(round(3.14159, 2)) # 3.14
print(abs(-10)) # 10
print(divmod(10, 3)) # (3, 1) 3 余 1
print(pow(2, 3)) # 8 2 的 3次方
print(sorted([3, 1, 2])) # [1, 2, 3]
print(sorted([3, 1, 2], reverse=True)) # [3, 2, 1]
# 也可以针对字符串进行排序
# 优先级为 大写首字母, 小写首字母,汉字
print(sorted(['apple', 'Xiaomi', 'huawei', '看见'])) # ['Xiaomi', 'apple', 'huawei', '看见']
# 可以通过字母大小写转换排序
print(sorted(['apple', 'Xiaomi', 'huawei', '看见'], key=str.lower)) # ['apple', 'huawei', 'Xiaomi', '看见']