zoukankan      html  css  js  c++  java
  • 『Python』整洁之道

    1. 使用 assert 加一层保险

    断言是为了告诉开发人员程序中发生了不可恢复的错误,对于可以预料的错误(如文件不存在),用户可以予以纠正或重试,断言并不是为此而生的。

    断言用于程序内部自检,如声明一些代码中不可能出现的条件,如果触发了某个条件,即意味着程序中存在着相应的bug。

    Python断言是一种调试辅助功能不是用来处理运行时错误的机制

    语法:assert expression1 [, expression2]

    expresssion1 是要判断的表达式,expression2 是可选的,用于返回错误信息

    【注意】

    • 不要使用断言验证数据,因为有可能程序被禁用断言
    • 不要写出永远不会失败的断言

    2. 巧妙放置逗号

    举个例子就明白了

    names = ['Alice',
            'Bob',
            'Alex',
            ]
    

    这样可以删除任意一行元素,或者随意添加元素也方便,不用管逗号问题。

    3. 上下文管理器和 with 语句

    with 语句有助于简化一些通用资源管理模式,抽象出其中的功能,将其分解并重用。

    with open("hello.txt", 'w') as f:
        f.write('hello world!')
    

    避免忘记手动关闭 IO 流

    这样代码既好懂,又简洁,我们可以在自定义对象中支持 with

    只要实现所谓的上下文管理器,就可以在自定义的类和函数中获得相同的功能。

    简单点,如果想将一个对象作为上下文管理器,需要做的就是向其中添加__enter____exit__方法。下面以open()为例,简单手动实现一个上下文管理器。

    class ManageFile(object):
        def __init__(self, name):
            self.name = name
        
        def __enter__(self):
            self.file = open(self.name, 'w')
            return self.file
        
        def __exit__(self, exc_type, exc_val. exc_tb):
            if self.file:
                self.file.close()
                
    

    至此,我们可以这样调用:

    with ManageFile('hello.txt') as f:
        f.write('hello world!')
        f.write('bye now!')
        
    

    当流程进入with语句上下文时,Python会调用__enter__获取资源,离开with上下文时,Python会调用__exit__释放资源。

    上面的是原始的套路,实际使用当然有简化版。标准库中的contextlib模块在上下文管理器基本协议的基础上提供了更多抽象。如果遇到的情形正好能用到contextlib提供而功能,那么可以节省很多精力。

    【例1】

    from contextlib import contextmanager
    
    @contextmanager
    def make_open_context(filename, mode):
        fp = open(filename, mode)
        try:
            yield fp
        finally:
            fp.close()
    
    with make_open_context('/tmp/a.txt', 'a') as file_obj:
        file_obj.write("hello carson666")
        
    

    【例2】

    # _*_ coding:utf-8 _*_
    from contextlib import contextmanager
    
    """
    contextmanager给了我们一个机会,即将原来不是上下文管理器的类变成了一个
    上下文管理器,例如这里的MyResource类
    """
    
    
    class MyResource:
        def query(self):
            print("query data")
    
    
    @contextmanager
    def make_myresource():
        print("connect to resource")
        yield MyResource()
        print("connect to resource")
    
    
    with make_myresource() as r:
        r.query()
    

    输出:

    connect to resource
    query data
    connect to resource
    

    【例3】

    # _*_ coding:utf-8 _*_
    
    from contextlib import contextmanager
    
    
    @contextmanager
    def book_mark():
        print('《', end="")
        yield
        print('》', end="")
    
    
    with book_mark():
        # 核心代码
        print('且将生活一饮而尽', end="")
    
    

    输出:

    《且将生活一饮而尽》
    

    以上就是对类和函数实现上下文管理的方法

    4. 下划线、双下划线及其他

    4.1 前置单下划线:_var

    当涉及变量名和方法时,前置单下划线只有约定含义,并不强制,只是提醒使用者不要在外部调用。

    Python中如果使用通配符*导入一个模块所有包,此时不会导入带前置单下划线的名称(除非__all__列表定义覆盖)

    顺带说一下,应避免使用通配符导入,疑问这样就不清楚你在该文件使用了什么名称,常规导入是可以将前置单下划线的名称引入的。

    4.2 后置单下划线:var_

    有时,某个变量最适合额名称已被Python中关键字占用,在这种情况下,可以追加一个下划线来绕过命名冲突。

    PEP8已定义并解释了这个约定

    如果你使用过numpy这些科学计算库,你会发现里面也有后置单下划线的函数,这种函数一般代表的是原位操作,去掉后置单下划线则是通常操作,返回的是clone后的对象。

    4.3 前置双下划线:__var

    双下划线前缀会让Python解释器重写属性名称,以避免子类中额命名冲突。下面来试验一下:

    class Test(object):
        def __init__(self):
            self.foo = 11
            self._bar = 22
            self.__baz = 33
    
    
    t = Test()
    print(dir(t))
    

    输出:

    ['_Test__baz', '__class__', '__delattr__', '__dict__', '__dir__', 
    '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', 
    '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', 
    '__lt__', '__module__', '__ne__', '__new__', '__reduce__', 
    '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', 
    '__subclasshook__', '__weakref__', '_bar', 'foo']
    

    你会发现,前两个变量都有,而第三个变量则没有了,它被名称改写为_Test__baz了,是为了防止子类覆盖这些变量。

    名称改写可用于属性和方法名,并且,名称改写并不与类属性绑定。

    4.4 前后双下划线:__var__

    双下划线的方法通常被称为魔法方法,重写这类方法时,一般是为了实现某种Python语言特性。

    例如前面遇到的上下文管理器的实现。

    4.5 单下划线:_

    一般,若果你的函数返回值有多个,而你并不是所有都需要,那么你对不需要的返回值可以用_接收。

    5. 格式化字符串

    具体的使用规则不再赘述,这里主要谈谈如何选用Python的四种格式化字符串:

    如果格式化字符串是用户提供的,使用模板字符串来避免安全问题。如果不是,再考虑Python版本:Python 3.6+使用字符串字面值插值,老版本则使用“新式”字符串格式化。

  • 相关阅读:
    Android PopupWindow显示位置和显示大小
    线性回归与梯度下降
    nginx启动过程分析
    项目管理学习笔记之三.绩效分析
    会计总论读书笔记
    电子书阅读及工具
    mybatis-mysql小优化
    List去重
    JAVA8之lambda表达式详解,及stream中的lambda使用
    linux部署mongodb及基本操作
  • 原文地址:https://www.cnblogs.com/ice-coder/p/12809895.html
Copyright © 2011-2022 走看看