enter & exit
在python中实现了enter和exit方法,即支持上下文管理器协议。上下文管理器就是支持上下文管理器协议的对象,它是为了with而生。当with语句在开始运行时,会在上下文管理器对象上调用 enter 方法。with语句运行结束后,会在上下文管理器对象上调用 exit 方法。
with的语法:
with EXPR as VAR:
BLOCK
with事实上等价于以下代码:
mgr = (EXPR)
exit = type(mgr).__exit__ # Not calling it yet
value = type(mgr).__enter__(mgr)
exc = True
try:
try:
VAR = value # Only if "as VAR" is present
BLOCK
except:
# The exceptional case is handled here
exc = False
if not exit(mgr, *sys.exc_info()):
raise
# The exception is swallowed if exit() returns true
finally:
# The normal and non-local-goto cases are handled here
if exc:
exit(mgr, None, None, None)
就是with语句是一个异常检测语句的简化版,能够减少代码量!但是如果在init或者enter中抛出异常,则不会进入到exit中。
利用with打开文件(其可以实现自动关闭文件,检测错误等):
with open('hello.txt','w') as f:
f.write('hello!') // 其中f为open对象中的__enter__的返回值
例子:
class VideoTracker(object):
def __init__(self, cfg, args, video_path):
self.cfg = cfg
self.args = args
self.video_path = video_path
self.logger = get_logger("root")
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, exc_traceback):
if exc_type:
print(exc_type, exc_value, exc_traceback)
def run(self):
#TODO
with VideoTracker(cfg, args, video_path=args.VIDEO_PATH) as vdo_trk:
vdo_trk.run()
argparse
实现对参数的管理。
python安装包
python实现包的动态导入
import
__import__(name, globals, locals, fromlist, level)
只有name
是必选参数,其他都是可选参数,一般情况下直接使用name
参数即可。
fromlist
指明需要导入的子模块名level
指定导入方式(相对导入或者绝对导入, 默认两者都支持)
注意事项:
- 如果
fromlist
是空的话(默认为空),那么返回的将是顶层模块,基于此下面两句代码表示相同的意思
__import__('models.model')
__import__('models.model.dataset')
两句代码返回的结果都是**models**
- 如果
fromlist
非空的话,那么就可以返回子模块
__import__('models.model.dataset',fromlist=['dataset'])
这句代码将返回**models.model.dataset**
(这里fromlist里面的子模块并没有限制,即使该子模块不存在,上面那句话也不会出错,照常可以导入其它存在的模块)
其中的dataset对应的是py文件(即必须是模块)
不是模块的话,则需采用from models.model import dataset
(从而导入模块中的类)
模块的含义:文件夹或者py文件 模块内部的函数和类就是模块的内部属性
def import_class(name, fromlist=[]):
module = __import__(name=name, fromlist=fromlist)
return module
# equal to: import numpy
np = import_class('numpy')
print(np.zeros(3))
# equal to: import models.model as model
model = import_class('models.model', fromlist=['Model'])
print(model.Model())
Linux 环境中配置 Python 外部包的路径
步骤如下:
- 安装外部包,获取其安装路径;
在 ~/.bashrc 中对 python 路径进行外部导入:
vim ~/.bashrc
## 在最后一行添加
export PYTHONPATH="yourpath:$PYTHONPATH"
## 保存退出
source ./bashrc
当然也可以在python程序中,利用 sys 模块进行动态添加
Python 迭代器
python 中像 list, set, string 以及 dict 都是可迭代的对象,可以用 iter() 函数获取迭代器,之后就可以 next() 进行遍历了。
L = [1, 2, 3]
myiter = iter(L)
while True:
try:
print(next(myiter))
except StopIteration:
print('Finish!')
break
创建迭代器
只需要在类中实现 iter 和 _next 函数即可,之后借助 iter()_ 函数获取迭代器。
class myiter:
def __init__(self):
self.data = [1, 2, 3]
self.index = 0
self.length = 3
def __iter__(self):
# 需要返回自身
return self
def __next__(self):
# 获取下一个数
if self.index >= self.length:
raise StopIteration
else:
value = self.data[index]
self.index += 1
return value
Python 生成器
python 生成器不是将数据一下子创建出来,而是需要用到什么数据就产生什么数据。这种方式能够降低内存占用。
创建生成器
- 例如 List 的列表生产式 L = [ True for in range(10) ] 如果,我们改为 G = (True for i in range(10)) _就可以得到一个生成器。
G = (True for _ in range(10)) G
at 0x7fb0ba796350>
然后可以采用 next() 函数获取相应的值(和迭代器类似,获取到 StopIteration 异常即结束)。
- 在函数中加入 yield 关键字,yield 类似于 return,每次会返回一个值
- 每次迭代,到 yield 结束,下一次迭代从 yield 下一条代码开始执行
- 函数走走停停
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done'
test = fib(3)
next(test) # output 1
next(test) # output 1
next(test) # output 2
next(test) # StopIteration: done