【测试语言篇二】Python进阶篇:lambda函数、异常和错误处理、Json处理、随机数、星号操作符
目录
一、Lambda 函数
使用示例:另一个函数内的Lambda函数
使用lambda函数作为key参数的自定义排序
map 函数中使用 Lambda 函数
filter 函数中使用 Lambda 函数
reduce函数中使用Lambda函数
二、异常和错误
语法错误
异常
抛出异常
处理异常
else 语句
finally 语句
常见的内置异常
如何定义自己的异常
三、JSON
JSON格式
从Python到JSON(序列化,编码)
从JSON到Python(反序列化,解码)
使用自定义对象
编码
解码
模板编码和解码函数
四、随机数
random 模块
种子生成器
secrets 模块
NumPy的随机数
五、星号操作符
乘法和幂运算
创建具有重复元素的列表,元组或字符串
*args, **kwargs 和仅关键字参数
拆包函数参数
拆包容器
将可迭代对象合并到列表中/合并字典
一、Lambda 函数
Python使用lambda来创建匿名函数。
Lambda函数是一个小的(一行)、匿名的、内联函数,没有函数名称。 Lambda函数可以接受任意数量的参数,但只能具有一个表达式。
匿名函数不要使用def关键字来定义完整函数。
lambda 函数特点:
- lambda 函数是匿名的,它们没有函数名称,只能通过赋值给变量或作为参数传递给其他函数来使用。
- lambda 函数通常只包含一行代码,这使得它们适用于编写简单的函数。
lambda 语法格式: lambda arguments: expression
lambda
是 Python 的关键字,用于定义 lambda 函数。arguments
是参数列表,可以包含零个或多个参数,但必须在冒号(:
)前指定。expression
是一个表达式,用于计算并返回函数的结果。
当简单函数仅在代码中使用一次或短时间时,可以使用Lambda函数。 最常见的用途是作为高阶函数(将其他函数作为参数的函数)的参数。 它们还与诸如 map()
, filter()
, reduce()
之类的内置函数一起使用。
# 一个给参数加10的lambda函数
f = lambda x: x+10
val1 = f(5)
val2 = f(100)
print(val1, val2)# 一个返回两个参数乘积的lambda函数
f = lambda x,y: x*y
val3 = f(2,10)
val4 = f(7,5)
print(val3, val4)
15 11020 35
使用示例:另一个函数内的Lambda函数
从另一个函数返回定制的lambda函数,并根据需要创建不同的函数变体。
def myfunc(n):return lambda x: x * ndoubler = myfunc(2)
print(doubler(6))tripler = myfunc(3)
print(tripler(6))
1218
使用lambda函数作为key参数的自定义排序
key函数会在排序之前转换每个元素。
points2D = [(1, 9), (4, 1), (5, -3), (10, 2)]
sorted_by_y = sorted(points2D, key= lambda x: x[1])
print(sorted_by_y)mylist = [- 1, -4, -2, -3, 1, 2, 3, 4]
sorted_by_abs = sorted(mylist, key= lambda x: abs(x))
print(sorted_by_abs)
[(5, -3), (4, 1), (10, 2), (1, 9)][-1, 1, -2, 2, -3, 3, -4, 4]
map 函数中使用 Lambda 函数
map(func, seq)
,使用函数转换每个元素。
a = [1, 2, 3, 4, 5, 6]
b = list(map(lambda x: x * 2 , a))# 但是,尝试使用列表推导
# 如果你已经定义了函数,请使用 map
c = [x*2 for x in a]
print(b)
print(c)numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x**2, numbers))
print(squared)
[2, 4, 6, 8, 10, 12][2, 4, 6, 8, 10, 12][1, 4, 9, 16, 25]
filter 函数中使用 Lambda 函数
filter(func, seq)
,返回其 func
计算为 True
的所有元素。
#使用 lambda 函数与 filter() 一起,筛选偶数:
a = [1, 2, 3, 4, 5, 6, 7, 8]
b = list(filter(lambda x: (x%2 == 0) , a))# 同样可以使用列表推导实现
c = [x for x in a if x%2 == 0]
print(b)
print(c)
[2, 4, 6, 8][2, 4, 6, 8]
reduce函数中使用Lambda函数
reduce(func, seq)
,重复将 func
应用于元素并返回单个值。func
需要2个参数。
from functools import reduce
numbers = [1, 2, 3, 4, 5]
product_a = reduce(lambda x, y: x*y, numbers)
print(product_a)
sum_a = reduce(lambda x, y: x+y, numbers)
print(sum_a)
12015 在上面的实例中,reduce() 函数通过遍历 numbers 列表,并使用 lambda 函数将累积的结果不断更新,最终得到了 1 * 2 * 3 * 4 * 5 = 120 的结果。
二、异常和错误
Python程序在遇到错误后立即终止。在Python中,错误可以是语法错误或异常。 在本文中,我们将关注以下内容:
-
语法错误与异常
-
如何抛出异常
-
如何处理异常
-
常见的内置异常
-
如何定义自己的异常
语法错误
当解析器检测到语法不正确的语句时发生语法错误。 语法错误可以是例如拼写错误,缺少括号,没有新行(请参见下面的代码)或错误的标识(这实际上会引发它自己的IndentationError,但它是SyntaxError的子类)。
a = 5 print(a)
File "<ipython-input-5-fed4b61d14cd>", line 1a = 5 print(a)^SyntaxError: invalid syntax
异常
即使一条语句在语法上是正确的,执行该语句也可能导致错误,这称为 异常错误。 有几种不同的错误类别,例如,尝试对数字和字符串求和将引发 TypeError
。
a = 5 + '10'
---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-6-893398416ed7> in <module>----> 1 a = 5 + '10'TypeError: unsupported operand type(s) for +: 'int' and 'str'
抛出异常
如果要在满足特定条件时强制发生异常,则可以使用 raise
关键字。
x = -5 if x < 0:raise Exception('x should not be negative.')
---------------------------------------------------------------------------Exception Traceback (most recent call last)<ipython-input-4-2a9e7e673803> in <module>1 x = -52 if x < 0:----> 3 raise Exception('x should not be negative.')Exception: x should not be negative.
你还可以使用 assert
语句,如果你的断言不是 True
,则将引发 AssertionError
。 这样,你可以主动测试必须满足的某些条件,而不必等待程序中途崩溃。 断言还用于单元测试。
x = -5 assert (x >= 0), 'x is not positive.' # --> 如果 x >= 0,代码将正常运行
---------------------------------------------------------------------------AssertionError Traceback (most recent call last)<ipython-input-7-f9b059c51e45> in <module>1 x = -5----> 2 assert (x >= 0), 'x is not positive.'3 # --> Your code will be fine if x >= 0AssertionError: x is not positive.
处理异常
你可以使用 try
和 except
块来捕获和处理异常。 如果你可以捕获异常,则你的程序将不会终止,并且可以继续。
# 这将捕获所有可能的异常
try:a = 5 / 0
except:print('some error occured.')# 可以捕获异常类型
try:a = 5 / 0
except Exception as e:print(e)# 最好指定要捕获的异常类型
# 因此,你必须知道可能的错误
try:a = 5 / 0
except ZeroDivisionError:print('Only a ZeroDivisionError is handled here')# 你可以在try块中运行多个语句,并捕获不同的可能的异常
try:a = 5 / 1 # 注意:这里没有 ZeroDivisionErrorb = a + '10'
except ZeroDivisionError as e:print('A ZeroDivisionError occured:', e)
except TypeError as e:print('A TypeError occured:', e)
Some error occured.Division by zeroOnly a ZeroDivisionError is handled hereA TypeError occured: unsupported operand type(s) for +: 'float' and 'str'
else
语句
如果没有发生异常,则可以使用else语句运行。
try:a = 5 / 1
except ZeroDivisionError as e:print('A ZeroDivisionError occured:', e)
else:print('Everything is ok')
Everything is ok
finally
语句
你可以使用始终运行的 finally
语句,无论是否存在异常。 例如,这可用于进行一些清理操作。
try:a = 5 / 1 # 注意:这里没有 ZeroDivisionErrorb = a + '10'
except ZeroDivisionError as e:print('A ZeroDivisionError occured:', e)
except TypeError as e:print('A TypeError occured:', e)
else:print('Everything is ok')
finally:print('Cleaning up some stuff...')
A TypeError occured: unsupported operand type(s) for +: 'float' and 'str'Cleaning up some stuff...
常见的内置异常
你可以在此处找到所有内置的异常:https://docs.python.org/3/library/exceptions.html
-
ImportError
:如果无法导入模块 -
NameError
:如果你尝试使用未定义的变量 -
FileNotFoundError
:如果你尝试打开一个不存在的文件或指定了错误的路径 -
ValueError
:当某个操作或函数收到类型正确但值不正确的参数时,例如尝试从不存在的列表中删除值 -
TypeError
:将操作或函数应用于不适当类型的对象时引发。 -
IndexError
:如果你尝试访问序列的无效索引,例如列表或元组。 -
KeyError
:如果你尝试访问字典中不存在的键。
# ImportError
import nonexistingmodule# NameError
a = someundefinedvariable# FileNotFoundError
with open('nonexistingfile.txt') as f:read_data = f.read()# ValueError
a = [0, 1, 2]
a.remove(3)# TypeError
a = 5 + "10"# IndexError
a = [0, 1, 2]
value = a[5]# KeyError
my_dict = {"name": "Max", "city": "Boston"}
age = my_dict["age"]
如何定义自己的异常
你可以定义自己的异常类,该异常类应从内置的 Exception
类派生。 与标准异常的命名类似,大多数异常都以“错误”结尾的名称定义。 可以像定义其他任何类一样定义异常类,但是它们通常保持简单,通常仅提供一定数量的属性,这些属性允许处理程序提取有关错误的信息。
# 自定义异常类的最小示例
class ValueTooHighError(Exception):pass# 或者为处理者添加一些信息
class ValueTooLowError(Exception):def __init__(self, message, value):self.message = messageself.value = valuedef test_value(a):if a > 1000:raise ValueTooHighError('Value is too high.')if a < 5:raise ValueTooLowError('Value is too low.', a) # 注意,构造器接受两个参数return atry:test_value(1)
except ValueTooHighError as e:print(e)
except ValueTooLowError as e:print(e.message, 'The value is:', e.value)
Value is too low. The value is: 1
三、随机数
Python定义了一组用于生成或操作随机数的函数。 本文介绍:
-
random
模块 -
用
random.seed()
再生产数字 -
使用
secrets
模块创建密码学上强的随机数 -
用
numpy.random
创建随机 nd 数组
random
模块
该模块为各种版本实现伪随机数生成器。它使用Mersenne Twister算法(https://en.wikipedia.org/wiki/Mersenne_Twister)作为其核心生成器。 之所以称其为伪随机数,是因为数字看起来是随机的,但是是可重现的。
import random# [0,1) 之间随机浮点数
a = random.random()
print(a)# [a,b] 之间随机浮点数
a = random.uniform(1,10)
print(a)# [a,b] 之间随机整数,b 包括。
a = random.randint(1,10)
print(a)# 之间随机整数,b 不包括。
a = random.randrange(1,10)
print(a)# 参数为 mu 和 sigma 的正态分布随机浮点数
a = random.normalvariate(0, 1)
print(a)# 从序列中随机选择元素
a = random.choice(list("ABCDEFGHI"))
print(a)# 从序列中随机选择 k 个唯一元素
a = random.sample(list("ABCDEFGHI"), 3)
print(a)# 选择可重复的k个元素,并返回大小为k的列表
a = random.choices(list("ABCDEFGHI"),k=3)
print(a)# 原地随机排列
a = list("ABCDEFGHI")
random.shuffle(a)
print(a)
0.104263734520673173.3498397935244434-1.004568769635799E['G', 'C', 'B']['E', 'D', 'E']['D', 'I', 'G', 'H', 'E', 'B', 'C', 'F', 'A']
种子生成器
使用 random.seed()
,可以使结果可重复,并且 random.seed()
之后的调用链将产生相同的数据轨迹。 随机数序列变得确定,或完全由种子值确定。
print('Seeding with 1...\n')random.seed(1)
print(random.random())
print(random.uniform(1,10))
print(random.choice(list("ABCDEFGHI")))print('\nRe-seeding with 42...\n')
random.seed(42) # 重设随机种子print(random.random())
print(random.uniform(1,10))
print(random.choice(list("ABCDEFGHI")))print('\nRe-seeding with 1...\n')
random.seed(1) # 重设随机种子print(random.random())
print(random.uniform(1,10))
print(random.choice(list("ABCDEFGHI")))print('\nRe-seeding with 42...\n')
random.seed(42) # 重设随机种子print(random.random())
print(random.uniform(1,10))
print(random.choice(list("ABCDEFGHI")))
Seeding with 1...0.134364244112401228.626903632435095BRe-seeding with 42...0.63942679845788371.2250967970040025ERe-seeding with 1...0.134364244112401228.626903632435095BRe-seeding with 42...0.63942679845788371.2250967970040025E
secrets
模块
secrets
模块用于生成适合于管理数据(例如密码,帐户身份验证,安全令牌和相关机密)的密码学上强的随机数。
特别是,应优先使用secrets
而不是 random
模块中默认的伪随机数生成器,后者是为建模和仿真而设计的,而不是安全或加密技术。
import secrets# [0, n) 之间的随机整数。
a = secrets.randbelow(10)
print(a)# 返回具有k个随机位的整数。
a = secrets.randbits(5)
print(a)# 从序列中选择一个随机元素
a = secrets.choice(list("ABCDEFGHI"))
print(a)
66E
NumPy的随机数
为多维数组创建随机数。NumPy伪随机数生成器与Python标准库伪随机数生成器不同。
重要的是,设置Python伪随机数生成器种子不会影响NumPy伪随机数生成器,必须单独设置和使用。
import numpy as npnp.random.seed(1)
# rand(d0,d1,…,dn)
# 生成随机浮点数的多维数组, 数组大小为 (d0,d1,…,dn)
print(np.random.rand(3))
# 重设随机种子
np.random.seed(1)
print(np.random.rand(3))# 生成 [a,b) 之间随机整数的多维数组,大小为 n
values = np.random.randint(0, 10, (5,3))
print(values)# 使用正态分布值生成多维数组,数组大小为 (d0,d1,…,dn)
# 来自标准正态分布的平均值为0.0且标准偏差为1.0的值
values = np.random.randn(5)
print(values)# 随机排列一个多维数组.
# 仅沿多维数组的第一轴随机排列数组
arr = np.array([[1,2,3], [4,5,6], [7,8,9]])
np.random.shuffle(arr)
print(arr)
[4.17022005e-01 7.20324493e-01 1.14374817e-04][4.17022005e-01 7.20324493e-01 1.14374817e-04][[5 0 0][1 7 6][9 2 4][5 2 4][2 4 7]][-2.29230928 -1.41555249 0.8858294 0.63190187 0.04026035][[4 5 6][7 8 9][1 2 3]]
四、星号操作符
星号( *
)可用于Python中的不同情况:
-
乘法和幂运算
-
创建具有重复元素的列表,元组或字符串
-
*args
,**kwargs
和仅关键字参数 -
拆包列表/元组/字典的函数参数
-
拆包容器
-
将可迭代对象合并到列表中/合并字典
乘法和幂运算
# 乘法
result = 7 * 5
print(result)# 幂运算
result = 2 ** 4
print(result)
3516
创建具有重复元素的列表,元组或字符串
# list
zeros = [0] * 10
onetwos = [1, 2] * 5
print(zeros)
print(onetwos)# tuple
zeros = (0,) * 10
onetwos = (1, 2) * 5
print(zeros)
print(onetwos)# string
A_string = "A" * 10
AB_string = "AB" * 5
print(A_string)
print(AB_string)
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0][1, 2, 1, 2, 1, 2, 1, 2, 1, 2](0, 0, 0, 0, 0, 0, 0, 0, 0, 0)(1, 2, 1, 2, 1, 2, 1, 2, 1, 2)AAAAAAAAAAABABABABAB
*args
, **kwargs
和仅关键字参数
-
对可变长度参数使用
*args
-
对长度可变的关键字参数使用
**kwargs
-
使用
*
,后跟更多函数参数以强制使用仅关键字的参数
def my_function(*args, **kwargs):for arg in args:print(arg)for key in kwargs:print(key, kwargs[key])my_function("Hey", 3, [0, 1, 2], name="Alex", age=8)# '*' 或 '* identifier' 之后的参数是仅关键字参数,只能使用关键字参数传递。
def my_function2(name, *, age):print(name)print(age)# my_function2("Michael", 5) --> 这会引发 TypeError 错误
my_function2("Michael", age=5)
Hey3[0, 1, 2]name Alexage 8Michael5
拆包函数参数
-
如果长度与参数匹配,则列表/元组/集合/字符串可以用
*
拆成函数参数。 -
如果长度和键与参数匹配,则字典可以用两个
**
拆包。
def foo(a, b, c):print(a, b, c)# 长度必需匹配
my_list = [1, 2, 3]
foo(*my_list)my_string = "ABC"
foo(*my_string)# 长度和键必需匹配
my_dict = {'a': 4, 'b': 5, 'c': 6}
foo(**my_dict)
1 2 3A B C4 5 6
拆包容器
将列表,元组或集合的元素拆包为单个和多个剩余元素。 请注意,即使被拆包的容器是元组或集合,也将多个元素组合在一个列表中。
numbers = (1, 2, 3, 4, 5, 6, 7, 8)*beginning, last = numbers
print(beginning)
print(last)print()first, *end = numbers
print(first)
print(end)print()
first, *middle, last = numbers
print(first)
print(middle)
print(last)
[1, 2, 3, 4, 5, 6, 7]81[2, 3, 4, 5, 6, 7, 8]1[2, 3, 4, 5, 6, 7]8
将可迭代对象合并到列表中/合并字典
由于PEP 448(PEP 448 – Additional Unpacking Generalizations | peps.python.org),从Python 3.5开始,这是可能的。
# 将可迭代对象合并到列表中
my_tuple = (1, 2, 3)
my_set = {4, 5, 6}
my_list = [*my_tuple, *my_set]
print(my_list)# 用字典拆包合并两个字典
dict_a = {'one': 1, 'two': 2}
dict_b = {'three': 3, 'four': 4}
dict_c = {**dict_a, **dict_b}
print(dict_c)
[1, 2, 3, 4, 5, 6]{'one': 1, 'two': 2, 'three': 3, 'four': 4}
但是,请注意以下合并解决方案。 如果字典中有任何非字符串键,则它将不起作用:https://stackoverflow.com/questions/38987/how-to-merge-two-dictionaries-in-a-single-expression/39858#39858
dict_a = {'one': 1, 'two': 2}
dict_b = {3: 3, 'four': 4}
dict_c = dict(dict_a, **dict_b)
print(dict_c)# 以下可行:
# dict_c = {**dict_a, **dict_b}
---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-52-2660fb90a60f> in <module>1 dict_a = {'one': 1, 'two': 2}2 dict_b = {3: 3, 'four': 4}----> 3 dict_c = dict(dict_a, **dict_b)4 print(dict_c)5 TypeError: keywords must be strings
推荐进一步阅读:
-
https://treyhunner.com/2018/10/asterisks-in-python-what-they-are-and-how-to-use-them/
-
https://treyhunner.com/2016/02/how-to-merge-dictionaries-in-python/