每日5个Python小技巧(day1)

每日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.前后双下划线

​ 某些前后双下划线名的方法在类中是表示一些特殊的方法,后续会慢慢揭晓。需要注意的是自定义变量名或函数名时,尽量避免使用前后双下划线的命名。

上一篇:Python 的 f-strings,远比你想象的要强大


下一篇:C# 类的封装