assert
(1)用法
assert expression, 'message'
当expression语句不满足的时候会raise一个AssertionError(报错),能确保assert语句以后的代码都满足expression。
(2)应用
告诉程序员发生不可恢复的错误,用于程序的内部自检,说明程序中不可能出现的情况。用于简单的自定义异常错误警告。
(3)注意
· 不能用于检验数据
在命令行中使用-o
和-oo
标识能全局禁用断言。
(4)例子
def AssertTest(num_): assert num_ > 10, 'num is less than 10' print(num_) if __name__ == '__main__': num = int(input("输入num: ")) AssertTest(num)
当输入3时,程序报错:
AssertionError: num is less than 10
(1)给自定义的对象添加__enter
和__exit__
方法。当执行流程进入with语句上下文时,Python会调用__enter
获取资源;离开with上下文时,Python会调用__exit__
释放资源.
(2)例子
class withClass: def __init__(self): self.resource = 0 def __enter__(self): self.resource += 1 print(f'获取资源resource: {self.resource}') def __exit__(self, exc_type, exc_val, exc_tb): self.resource = 0 print(f"释放资源resource: {self.resource}") if __name__ == '__main__': with withClass() as test: pass
输出:
获取资源resource: 1 释放资源resource: 0
(3)应用
文件的读写;数据的清洗或预处理;资源的自动获取与释放相关,避免资源的占用(如数据文件和数据库的连接等)。
@contextlib.contextmanager
(1)使用@contextlib.contextmanager
装饰器能够为资源定义一个基于生成器的工厂函数,该函数将自动支持with语句。
(2)引用一个例子
# 一个应用场景,给一个书名前后加上书名号 @contextmanager def book_mark(): print('《', end='') yield # yield 后面不一定要返回结果,纯粹起一个中断作用 print('》', end='') if __name__ == '__main__': # 衍生一种用法:在要执行的代码的前面和后面各补充一段代码 # 特别是对于一些框架的源码等,我们不能直接在源码里面修改 # 其次是追求封装性和复用性 with book_mark(): print("且将生活一饮而尽", end='')
[out] 《且将生活一饮而尽》
(3)例子2-一个简单的计时器
# 一个应用场景,给一个书名前后加上书名号 @contextmanager def timeit(): start = time.time() yield # yield 后面不一定要返回结果,纯粹起一个中断作用 end = time.time() print(f"耗时:{end-start}s") def func(): time.sleep(3) if __name__ == '__main__': with timeit() as test: func()
耗时:3.0065133571624756s
上下文管理器可充当于装饰器类似的作用,可以在不改变原函数的基础上增加一些方法,增强了封装性和复用性.
(1)前置单下划线
对程序本身没有影响,只是一种提示----Python社区约定好单下划线的变量或者方法只能在类的内部使用。
(2)后置单下划线
用于避免变量的命名与Python内置关键字冲突,例如bs4中用于查找<div class="container">...</div>
的标签,使用的参数class_='container'
;以及命名会与内置关键字冲突。
我通常会用单下划线标识函数中会与主函数相同的变量名。
(1)前置下划线
前置双下划线会让Python解释器重写属性名称,避免子类中的命名冲突。这也成为名称改写,即解释器会更改变量的名称。
a. 例子
_MyClass__myname = "myClass" class MyClass: def getMyname(self): print(__myname) if __name__ == '__main__': MyClass().getMyname()
[out] myClass
这个例子表明_MyClass__myname = "myClass"
为全局变量,然后再MyClass
的类环境中访问变量。由于名称改写,类中getMyname()
方法仅用__myname
就能引用_MyClass__myname
全局变量。
b. 双下划线也能为类表明私有属性
class MyClass: def __init__(self): self.__data = 1234 if __name__ == '__main__': mc = MyClass() print(mc.__data)
[out] AttributeError: 'MyClass' object has no attribute '__data'
然而用这个方法表明私有属性也存在风险,通过下面的方法也可以访问到data
mc = MyClass() print(mc._MyClass__data)
[out] 1234
c.前后双下划线
某些前后双下划线名的方法在类中是表示一些特殊的方法,后续会慢慢揭晓。需要注意的是自定义变量名或函数名时,尽量避免使用前后双下划线的命名。