每日5个Python小技巧-day1
1. 断言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
2.上下文管理:在自定义类中支持with语句
(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)应用
文件的读写;数据的清洗或预处理;资源的自动获取与释放相关,避免资源的占用(如数据文件和数据库的连接等)。
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
上下文管理器可充当于装饰器类似的作用,可以在不改变原函数的基础上增加一些方法,增强了封装性和复用性.
4. 单下划线
(1)前置单下划线
对程序本身没有影响,只是一种提示----Python社区约定好单下划线的变量或者方法只能在类的内部使用。
(2)后置单下划线
用于避免变量的命名与Python内置关键字冲突,例如bs4中用于查找<div class="container">...</div>
的标签,使用的参数class_='container'
;以及命名会与内置关键字冲突。
我通常会用单下划线标识函数中会与主函数相同的变量名。
5.双下划线
(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.前后双下划线
某些前后双下划线名的方法在类中是表示一些特殊的方法,后续会慢慢揭晓。需要注意的是自定义变量名或函数名时,尽量避免使用前后双下划线的命名。