Python学习笔记(7-1):若干高级功能
文章导读
- 课程难度:★★☆☆☆
- 重要度:★★★★☆
- 预计学习时间:30分钟
- 简介:本节主要讲解了进行数据分析时可以提高代码可读性、提升代码运行效率的一些高级功能,包括:(1)enumerate函数、zip函数;(2)eval和partial工具;(3)try-except的异常处理机制;(4)gc.collect内存管理与回收机制;(5)基于time类、timeit函数和tqdm包的程序运行时间分析;
- 重点涉及的函数和内容:enumerate()、zip()、eval()、partial()、try-except、gc.collect、timeit()、tqdm()
一、结合enumerate、zip函数的for循环
1、enumerate()
这个函数可以同时迭代列表、字典、Series或DataFrame等可迭代对象的下标和值:
a = [1,3,5,7,9]
for i,value in enumerate(a):
print(i) #输出列表的下标
输出结果如下:
0
1
2
3
4
a = [1,3,5,7,9]
for i,value in enumerate(a):
print(value) #输出列表的值
输出结果如下:
1
3
5
7
9
2、zip()
zip()
函数可以把多个可迭代对象中对应位置上的元素分别以元组的形式组合到一起:
data = zip('1234',[1,2,3,4,5,6])
print(data)
print(list(data)) #将zip对象转换为列表
输出结果如下:
<zip object at 0x000001AB44389700>
[('1', 1), ('2', 2), ('3', 3), ('4', 4)]
可以发现,当传入的序列不等长时,会在较短的序列循环完毕时停止本次循环。同时zip
对象时可迭代的,可以使用循环逐个遍历和访问。
二、函数处理时的eval和partial
1、eval()
这个函数可以将传入的字符串处理成可以执行的python代码,也可以用来计算字符串或字符串的值。
print(eval('8**2')) #求表达式的值
print(eval('[1,2,3,4,5]')) #对字符串求值得到列表
输出结果如下:
64
[1, 2, 3, 4, 5]
下面将举一个较实用的例子:
a = 10
def fune(x):
return x ** 2
string = 'fune(a)'
eval(string)
输出结果如下:
100
2、partial()
这个函数可以通过给定原函数中的一个或多个参数值而建成一个新函数
导包:
from functools import partial
它的用法我们结合一个基础的函数讲解,这个函数就是一个相减的过程:
def minus(a, b):
return a - b
我们利用partial()函数
,将参数b固定为100,并且给它一个别名。之后,我们给这个新函数只传递参数a就可以了:
minus_from100 = partial(minus, a=100)
minus_from100(2)
输出结果如下:
98
三、异常处理机制 - try-except
异常处理机制是处理程序运行时的异常和错误的,它可以包括try-except-else
和finally
四个部分,在此讲解常用的内容。首先,我们需要了解这几个部分使用的基础知识:
1、try是尝试执行的代码,except是在try代码出错之后跳转执行的代码,可以在except中报出异常类型。
2、try到执行到报错、跳转至except之前,所有代码都会被执行。
3、else是在try正常执行、没有遇到错误时会执行的代码。
4、finally是无论try正常执行、还是except执行之后都会执行的代码。
5、try语句必须要接一个except或是一个finally才保证语句的完整,但finally并不像except处理异常,try语句执行到第一个错误时仍然会报错退出。
6、书写else语句时必须要有一个except,此时不能用finally替代。
下面是一个把列表中数字和非数字分开的例子:
a = ['25', '3x', '7.2', '81', 'class', '60', 16]
a_num = []
a_nonum = []
for value in a:
try:
float(value)
except Exception as e:
print(e)
a_nonum.append(value)
else:
a_num.append(value)
finally:
print(str(value) + ' processed')
print(a_num, a_nonum)
输出结果如下:
25 processed
could not convert string to float: '3x'
3x processed
7.2 processed
81 processed
could not convert string to float: 'class'
class processed
60 processed
16 processed
(['25', '7.2', '81', '60', 16], ['3x', 'class'])
这里我们添加了将错误输出的部分。Exception
可以换成其他的错误类型,我们可以根据不同的异常类型采取不同的处理方式。Exception
是常规错误的基类,一般能报出我们程序里的异常,也可以将之换成BaseExecption
。
在try-except
之外,我们对异常处理做一个补充,介绍一个assert
语句,它的意思是在处理必须检查某个表达式,如果为假则直接抛出异常,思路相当于如果连这个条件也不满足那么直接报错退出,不用执行后续的操作了。
例如我们定义一个函数,在x为空值、异常值和nan
值时直接报错,同时,给出补充的错误信息(可有可无):
def fun(x):
assert x == x, 'x is nan'
assert x != None, 'x is None'
assert x != float('inf'), 'x is inf'
return x ** 2
在下面四个函数中,前面三个会直接报错,报出Assertion Error
print(fun(x = float('nan'))) # 报错1
print(fun(x = None)) # 报错2
print(fun(x = float('inf'))) # 报错3
print(fun(x = 2))
输出结果如下:
AssertionError: x is nan
AssertionError: x is None
AssertionError: x is inf
4
四、内存管理与回收 - gc.collect
在我们的程序面向较大的数据进行操作的时候,有可能一些对象不再被使用,但是它仍然占据着内存,这些对象一直保持对内存的使用,有可能造成内存的溢出,程序被迫中止。尽管python拥有自动回收内存的机制,但是在一些时候我们需要手动删除变量、以及手动回收内存。删除一个变量,用del
,手动回收内存,我们引入gc
(garbage collect)包。
import gc
a = [1, 2, 3, 4, 5]
del a # 删除这个元素
print(a) # 报错1:这个时候再来访问,我们就找不到这个变量了
【报错1】NameError: name 'a' is not defined
之后,我们用函数gc.collect()
进行垃圾清理,回收内存:
gc.collect()
五、程序运行时间分析
介绍一些用来查看并分析程序运行效率的工具,一个是timeit
,分析一个函数的运行时间,一个是tqdm
,查看一个循环的运行进程。
1、利用时间类去计算运行时间
这是一个最基础的方法,我们首先获取一个开始时间,代码运行结束后再来一个结束时间,计算时间差。
import time
time_start = time.time() # time.time()为1970.1.1到当前时间的毫秒数
value = 0
for i in range(10000000):
value += i
value = value % 7
time_end = time.time() # time.time()为1970.1.1到当前时间的毫秒数
print (time_end - time_start)
输出结果如下。输出的时间是程序运行的秒数:
2.4294142723083496
2、timeit()
这个函数传递一个以字符串形式表达的执行语句,也可以传递重复的次数number
,它的默认值为1000000。
利用timeit
查看一个函数的运行时间时,需要在函数代码后面,补充提供运行环境的字符串指示函数的位置,例如当前环境下就是__main__
:
# 定义一个函数
def fun(x, y, z):
for i in range(1000):
x += 1
y += x
z += y
return x, y, z
print(timeit('fun(3, 4, 5)', 'from __main__ import fun', number = 10000))
输出结果如下:
1.0419463999999998
如果我们想重复多次看平均时间,可以用一下timeit
包里的repeat
函数,重复多次运行函数,获取每一次的运行时间:
from timeit import repeat
print(repeat('fun(3, 4, 5)', 'from __main__ import fun', number = 10000, repeat = 10))
输出结果如下:
[1.0383742000000211,
1.0386617999999999,
1.035353299999997,
1.035814099999925,
1.0348183999999492,
1.0353870000000143,
1.04104540000003,
1.03712280000002,
1.0433005999999523,
1.0374408999999787]
3、tqdm()
这是一个针对for
循环(迭代器)使用的进度条工具tqdm
,这个工具使用很简单,就是用一个tqdm()
将这个迭代器括起来即可:
from tqdm import tqdm
import time
time_start = time.time()
value = 0
for i in tqdm(range(10000000)): # 用tqdm括起来就完了
value += i
value = value % 7
time_end = time.time()
print (time_end - time_start)
输出结果如下:
但是我们看一下,这里花费的时间,比在最初不带tqdm
的时候要长,主要原因是tqdm
本身也要占一定的系统资源。当然对于需要用这种查看进度条的(漫长的)循环来说,tqdm
占的资源一般不值一提。
这个工具的主要好处是能随时看这个程序的执行进度,并根据执行进度做出代码调整。还有一个隐含的好处在于,能够根据进度条上循环执行的速度变化来看出一些程序上的问题。
对于数据分析使用的高级功能还有更重要的一部分,即各类迭代函数,我们将在下一节进行详细的讲解。
对于缺乏Python基础的同仁,可以通过免费专栏🔥《Python学习笔记(基础)》从零开始学习Python
结语
请始终相信“Done is better than perfect”
,不要过分追求完美,即刻行动就是最好的开始, 一个模块一个模块地积累和练习,必将有所收获。
还有其他的问题欢迎在评论区留言📝!
[版权申明] 非商业目的注明出处可自由转载,转载请标明出处!!!
博客:butterfly_701c