1、纯函数
(1)、纯函数的概念
简单来说,一个函数的返回结果只依赖于它的参数,并且在执行过程里面没有副作用,我们就把这个函数叫做纯函数。
(2)、纯函数的三个原则
- 变量都只在函数作用内获取,作为的函数的参数传入。
- 不会产生副作用(side effects),不会改变被传入的数据或者其他数据(全局变量)
- 相同的输入保证相同的输
(3)函数的副作用
副作用是指函数被调用,完成了函数既定的计算任务,但同时因为访问了外部数据,尤其是因为对外部数据进行了写操作,从而一定程度地改变了系统环境
案例说明:
# 纯函数: 函数的返回值只和参数相关,执行的过程不会产生副作用。
def func1(a, b):
return a + b
# 非纯函数, 原因:返回的结果依赖于外部的环境的数据
var = 100
def func2(a):
return var + a
# 也不是纯函数 ,原因:这个函数执行有副作用,会对外部的环境里面的数据list进行修改
list = [11, 22, 33]
def func(a, b):
list.append(a)
list.append(b)
return a + b
2、匿名函数
匿名函数的定义:python中有一个特殊的函数,不需要使用def去定义,也不用给函数起名字,用lambda表达式来定义,这种函数叫匿名函数。
(1)匿名函数格式
lambda 参数: 表达式(返回值)
# 对比以前通过def写函数的时候的格式
def 函数名(参数):
函数体
# def常规函数定义
def func(x):
return x * 2
# 匿名函数定义
func1 = lambda x : x*2
(2)匿名函数的应用
① 需求1:对下面的列表进行排序(规则:根据列表中每个元素的第二个值的大小进行排序)
# 匿名函数的应用
# 问题需求:对下面的列表进行排序(规则:根据列表中每个元素的第二个值的大小进行排序)
li = [[1, 10, 32], [3, 22, 99], [2, 7, 77]]
def work(x):
return x[1]
# key传入排序规则函数
li.sort(key=work)
print(li)
# 打印结果
[[2, 7, 77], [1, 10, 32], [3, 22, 99]]
如果通过匿名函数去解决这个问题该怎么解决:
# 问题需求:对下面的列表进行排序(规则:根据列表中每个元素的第二个值的大小进行排序)
li = [[1, 10, 32], [3, 22, 99], [2, 7, 77]]
li.sort(key=lambda x: x[1])
print(li)
# 打印结果
[[2, 7, 77], [1, 10, 32], [3, 22, 99]]
② 需求2:对下面的列表进行排序(根据元素的name字段的值的大小进行排序)
# 问题需求2:对下面的列表进行排序(根据元素的name字段的值的大小进行排序)
li2 = [{"x": 1, "name": 100}, {"id": 7, "name": 9}, {"id": 3, "name": 11}]
def func(x):
return x["name"]
# 方法1
# li2.sort(key=func)
# print(li2)
# 方法2
li2.sort(key=lambda y: y["name"])
print(li2)
# 打印结果
[{'id': 7, 'name': 9}, {'id': 3, 'name': 11}, {'x': 1, 'name': 100}]
(3)多个参数的匿名函数
# 多个参数的匿名函数
func = lambda x, y, z: x + y + z
# 没有参数的匿名函数
func1 = lambda: 100
3、内置函数扩展(filter、map)
(1)filter函数:过滤器
- 参数1:过滤规则函数
- 参数2:可迭代对象
学了推导式基本上我们不用这个filter内置函数,这个过滤器,因为过滤器能做的,推导式也能完成(除了特别复杂的使用场景),下面我们来一个Demo:
# 需求:获取列表中大于30的数据
li = [11, 33, 34, 55, 7, 2, 7, 66, 899, 7, 5]
new_li = filter(lambda x: x > 30, li)
print(new_li) # 是一个filter对象,也是一个迭代器
# 需要把过滤器filter对象转换为列表
print(list(new_li))
# 打印结果
<filter object at 0x7fb07d091c70>
[33, 34, 55, 66, 899]
(2)map函数: 将函数应用于iterable中每一项并输出其结果,映射后再处理。
- 参数1:处理函数
- 参数2:可迭代对象
批量的去执行可迭代对象中每一个元素,对数据进行处理,上Demo
# map:将函数应用于iterable中每一项并输出其结果
# 将li中每一项的2次方计算出来
li = [11, 33, 34, 55, 7, 2, 7, 66, 899, 7, 5]
res = map(lambda x: x ** 2, li)
print(list(res))
# 打印结果
[121, 1089, 1156, 3025, 49, 4, 49, 4356, 808201, 49, 25]
如果map(lambda x: x > 2, li)返回结果是什么样子呢?
# map:将函数应用于iterable中每一项并输出其结果
li = [11, 33, 34, 55, 7, 2, 7, 66, 899, 7, 5]
res = map(lambda x: x > 2, li)
print(list(res))
# 打印结果
[True, True, True, True, True, False, True, True, True, True, True]
(3)exec:执行python代码,识别字符串中有效的python代码并执行
# 执行python代码,识别字符串中有效的python代码并执行
code = """
a=100
b=200
print(a+b)
"""
exec(code)
# 打印结果
300
如果在字符串code里面添加一个def方法,然后在外面去调用func()方法会报错,但是如果去执行了exec(code)之后,就没有问题,下面上代码。
code = """
a=100
b=200
print(a+b)
def func(x):
return x*2
"""
exec(code)
print(func(300))
# 打印结果
300
600
作用:以后开发测试平台,要执行一些前置后置脚本,那么从数据库里把前置脚本后置脚本读取出来之后,就可以使用这个方法去执行(后面我们搭建测试平台会实战运用)
(4) all:迭代对象内所有的元素为真,返回True
# all:迭代对象内所有的元素为真,返回True
def work(name=None, age=None, sex=None):
if name and age and sex:
print('----成立01----')
if all([name, age, sex]):
print('----成立02----')
work('wdx', 11, '男')
# 打印结果
----成立01----
----成立02----
(5)any:迭代对象内只要有一个元素为真,返回True
# all:迭代对象内所有的元素为真,返回True
def work(name=None, age=None, sex=None):
if name and age and sex:
print('----成立01----')
if any([name, age, sex]):
print('----成立02----')
work('wdx')
# 打印结果
----成立02----
(6)zip函数:聚合打包
如果我们使用常规语法 不使用zip打包会怎么做呢?
title = ['a', 'b', 'c']
value = [11, 22, 33]
dic = {}
for i in range(len(title)):
dic[title[i]] = value[i]
print(dic)
# 打印结果
{'a': 11, 'b': 22, 'c': 33}
直接使用zip打包
title = ['a', 'b', 'c']
value = [11, 22, 33]
# 直接使用zip打包
res = zip(title, value)
print(dict(res))
# 打印结果
{'a': 11, 'b': 22, 'c': 33}
那如果zip里面传入三个参数是什么情况呢?
a = [1, 2, 3]
bb = [11, 22, 33]
ccc = [111, 222, 333, 444]
# 直接使用zip打包
res = zip(a, bb, ccc)
print(list(res))
# 打印结果
[(1, 11, 111), (2, 22, 222), (3, 33, 333)]
由上面可以看出来 ccc多了一个元素444,其他列表只有三个元素,只有ccc有4个元素,那就自动把多了的元素去掉不会自动打包,以元素最短的那一条为基准。
实际运用:
从excel里面读取出来的数据如下,请把他转换成如下格式:
# 从excel里读取如下数据,转换成res1的格式
cases = [
['case_id', 'case_title', 'url', 'data', 'excepted'],
[1, '用例1', 'www.baudi.com', '001', 'ok'],
[4, '用例4', 'www.baudi.com', '002', 'ok'],
[2, '用例2', 'www.baudi.com', '002', 'ok'],
[3, '用例3', 'www.baudi.com', '002', 'ok'],
[5, '用例5', 'www.baudi.com', '002', 'ok'],
]
转换成如下格式
res1 = [
{'case_id': 1, 'case_title': '用例1', 'url': 'www.baudi.com', 'data': '001', 'excepted': 'ok'}
{'case_id': 4, 'case_title': '用例4', 'url': 'www.baudi.com', 'data': '002', 'excepted': 'ok'}
{'case_id': 2, 'case_title': '用例2', 'url': 'www.baudi.com', 'data': '002', 'excepted': 'ok'}
{'case_id': 3, 'case_title': '用例3', 'url': 'www.baudi.com', 'data': '002', 'excepted': 'ok'}
{'case_id': 5, 'case_title': '用例5', 'url': 'www.baudi.com', 'data': '002', 'excepted': 'ok'}
]
# 上代码,方法1常规操作:
titles = cases[0]
for i in cases[1:]:
res = dict(zip(titles, i))
print(res)
# 方法2:
result = [dict(zip(cases[0], i)) for i in cases[1:]]
print(result)
# 1、通过上述上课所学内置函数和推导式的语法,读取附件中excel文件,转换为如下的格式
# 1、通过上述上课所学内置函数和推导式的语法,读取附件中excel文件,转换为如下的格式
res1 = [{'case_id': 1, 'case_title': '用例1', 'url': 'www.baudi.com', 'data': '001', 'excepted': 'ok'},
{'case_id': 4, 'case_title': '用例4', 'url': 'www.baudi.com', 'data': '002', 'excepted': 'ok'},
{'case_id': 2, 'case_title': '用例2', 'url': 'www.baudi.com', 'data': '002', 'excepted': 'ok'},
{'case_id': 3, 'case_title': '用例3', 'url': 'www.baudi.com', 'data': '002', 'excepted': 'ok'},
{'case_id': 5, 'case_title': '用例5', 'url': 'www.baudi.com', 'data': '002', 'excepted': 'ok'}]
import openpyxl
res = openpyxl.load_workbook('data.xlsx')['login']
# 按行获取所有的数据
rows = res.rows
# 获取表头
title = [i.value for i in next(rows)]
result1 = []
for item in rows:
values = [i.value for i in item]
data = dict(zip(title, values))
result1.append(data)
# print(result1)
# 2、对第一题读取出来的数据,按照case_id字段进行排序。
result1.sort(key=lambda x: x['case_id'])
# print(result1)
# 3、将读取出来的数据中的method字段值 统一修改为GET(不需要修改excel,只对读出来的数据进行修改)
# 方法1
# for i in result1:
# i['method'] = 'get'
# print(result1)
# 方法二
map(lambda x: exec("i['method'] = 'get'"), result1)
print(result1)