enter以及exit

enter & exit

在python中实现了enterexit方法,即支持上下文管理器协议。上下文管理器就是支持上下文管理器协议的对象,它是为了with而生。当with语句在开始运行时,会在上下文管理器对象上调用 enter 方法。with语句运行结束后,会在上下文管理器对象上调用 exit 方法。
with的语法:

  1. with EXPR as VAR:
  2. BLOCK

with事实上等价于以下代码:

  1. mgr = (EXPR)
  2. exit = type(mgr).__exit__ # Not calling it yet
  3. value = type(mgr).__enter__(mgr)
  4. exc = True
  5. try:
  6. try:
  7. VAR = value # Only if "as VAR" is present
  8. BLOCK
  9. except:
  10. # The exceptional case is handled here
  11. exc = False
  12. if not exit(mgr, *sys.exc_info()):
  13. raise
  14. # The exception is swallowed if exit() returns true
  15. finally:
  16. # The normal and non-local-goto cases are handled here
  17. if exc:
  18. exit(mgr, None, None, None)

就是with语句是一个异常检测语句的简化版,能够减少代码量!但是如果在init或者enter中抛出异常,则不会进入到exit中。
利用with打开文件(其可以实现自动关闭文件,检测错误等):

  1. with open('hello.txt','w') as f:
  2. f.write('hello!') // 其中fopen对象中的__enter__的返回值

例子:

  1. class VideoTracker(object):
  2. def __init__(self, cfg, args, video_path):
  3. self.cfg = cfg
  4. self.args = args
  5. self.video_path = video_path
  6. self.logger = get_logger("root")
  7. def __enter__(self):
  8. return self
  9. def __exit__(self, exc_type, exc_value, exc_traceback):
  10. if exc_type:
  11. print(exc_type, exc_value, exc_traceback)
  12. def run(self):
  13. #TODO
  14. with VideoTracker(cfg, args, video_path=args.VIDEO_PATH) as vdo_trk:
  15. vdo_trk.run()

argparse

实现对参数的管理。

python安装包

  • 编写好代码,整理好相关的文件;
  • 编写init.py文件;
  • 编写setup.py文件;
  • python setup.py build;
  • python setup.py install;

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文件 模块内部的函数和类就是模块的内部属性

  1. def import_class(name, fromlist=[]):
  2. module = __import__(name=name, fromlist=fromlist)
  3. return module
  4. # equal to: import numpy
  5. np = import_class('numpy')
  6. print(np.zeros(3))
  7. # equal to: import models.model as model
  8. model = import_class('models.model', fromlist=['Model'])
  9. print(model.Model())

Linux 环境中配置 Python 外部包的路径

步骤如下:

  1. 安装外部包,获取其安装路径;
  2. 在 ~/.bashrc 中对 python 路径进行外部导入:

    1. vim ~/.bashrc
    2. ## 在最后一行添加
    3. export PYTHONPATH="yourpath:$PYTHONPATH"
    4. ## 保存退出
    5. source ./bashrc
  3. 当然也可以在python程序中,利用 sys 模块进行动态添加

Python 迭代器

python 中像 list, set, string 以及 dict 都是可迭代的对象,可以用 iter() 函数获取迭代器,之后就可以 next() 进行遍历了。

  1. L = [1, 2, 3]
  2. myiter = iter(L)
  3. while True:
  4. try:
  5. print(next(myiter))
  6. except StopIteration:
  7. print('Finish!')
  8. break

创建迭代器

只需要在类中实现 iter_next 函数即可,之后借助 iter()_ 函数获取迭代器。

  1. class myiter:
  2. def __init__(self):
  3. self.data = [1, 2, 3]
  4. self.index = 0
  5. self.length = 3
  6. def __iter__(self):
  7. # 需要返回自身
  8. return self
  9. def __next__(self):
  10. # 获取下一个数
  11. if self.index >= self.length:
  12. raise StopIteration
  13. else:
  14. value = self.data[index]
  15. self.index += 1
  16. 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,每次会返回一个值
    1. 每次迭代,到 yield 结束,下一次迭代从 yield 下一条代码开始执行
    2. 函数走走停停
  1. def fib(max):
  2. n, a, b = 0, 0, 1
  3. while n < max:
  4. yield b
  5. a, b = b, a + b
  6. n = n + 1
  7. return 'done'
  8. test = fib(3)
  9. next(test) # output 1
  10. next(test) # output 1
  11. next(test) # output 2
  12. next(test) # StopIteration: done