(二)纯函数、匿名函数、内置函数扩展

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)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值