美文网首页
用pythonic方式来思考(3)

用pythonic方式来思考(3)

作者: 小懒额 | 来源:发表于2018-05-01 10:31 被阅读0次
    第10条:尽量用 enumerate 取代 range

    内置 range 函数可以完成整数上的迭代,如:

    for i in range(5):
        print(i)
    >>>
    0
    1
    2
    3
    4
    

    然而对列表进行迭代时,还想知道索引的时候,如果用 range 函数,只能勉强这样:

    list = [1, 2, 3, 4, 5]
    for i in range(len(list)):
        print(i, list[i])
    >>>
    0 1
    1 2
    2 3
    3 4
    4 5
    

    python 提供了内置的 enumerate 函数,可以优雅的处理这种问题,

    list = [1, 2, 3, 4, 5]
    for index, value in enumerate(list):  # enumerate 把迭代器包装为生成器
        print(index, list[index])
    >>>
    0 1
    1 2
    2 3
    3 4
    4 5
    
    第11条:用 zip 函数同时遍历两个迭代器

    在同时遍历两个列表,而且两个列表之间存在关联的时候,就可以使用 zip 来进行迭代。zip 能够将两个和两个以上的迭代器中的值封装成生成器。

    name_list = ['xiaoli', 'xiaowu', 'xiaolan', 'xiaonwang']
    len_name = [len(n) for n in name_list]
    
    max_len = 0
    for name, len_name in zip(name_list, len_name):
        if len_name > max_len:
            max_len = len_name
            longest_name = name
    print(longest_name, max_len)
    >>>
    xiaonwang 9
    

    在 Python2 中zip不是生成器,而是迭代器产生的值的元组构成的列表,会占用大量内存。应该使用 itertools 中的 izip 函数。
    zip 函数遍历到任何一个迭代器结束时,就停止,所以如果有多个长度不同的迭代器时,在迭代次数最少的迭代器结束时就停止遍历其他的迭代器了。

    第12条:不要在 for 和 while 循环后面写 else 块

    Python 支持在循环内部的语句块后直接编写 else 块。

    for i in range(3):
        print('Loop %d' % i)
    else:
        print('Else block!')
    >>>
    Loop 0
    Loop 1
    Loop 2
    Else block!
    

    从上面运行实例可以看出,else 块在循环结束后直接执行。

    for i in range(3):
        print('Loop %d' % i)
        if i == 1:
            break
    else:
        print('Else block!')
    >>>
    Loop 0
    Loop 1
    Loop 2
    

    这时我们在 循环语句中加上 break 提前结束循环,这时就没有执行 else 块。while 语句也是如此,

    i = 0
    while True:
        i += 1
        print('Loop %d' % i)
        if i > 3:
            break
    else:
        print('Else block!')
    >>>
    Loop 0
    Loop 1
    Loop 2
    Loop 3
    

    所以, 循环后面的 else 只会在循环完全结束时才会执行,提前 break 出来时不会执行的。

    第13条:合理利用 try/except/else/finally 结构中的每个代码块

    Python 程序的异常处理可能要考虑四种不同的时机,这些时机可以用 try、except、else 和 finally 来表述。

    1.finally 块

    既要将异常向上传播,又要在异常发生时执行清理工作,就可以使用 try/finally 结构。这种结构可以用来确保程序能够可靠地关闭文件句柄。

    handle = open('/tmp/random_data.txt')  #open 放在 try 外面,否则open时IOError异常不会进入finally
    try:
        data = handle.read()
    finally:
        handle.close()
    
    2.else块

    在 try/else模块中,如果 try 块没有异常,就会执行 else 块。有了这个,就应该缩减 try 内的代码量,使其更加易读。
    例如在字符串中加载 json 字典数据,返回字典里某个键所对应的值:

    def load_json_key(data, key):
        try:
            result_dict = json.loads(data)
        except ValueError as e:
            raise  KeyError from e
        else:
            return result_dict[key]
    

    这种写法使异常行为更加清晰。

    3.混合使用

    如果在复合语句中把上面几种机制都用到的话,可以使代码更简洁易懂。
    比如在读取文件内容并对读取内容进行处理时,可以这样:

    def devide_json(path):
        handle = open(path, 'r+')
        try:
            data = handle.read()
            op = json.loads(data)
            value = (
                op['numerator']/
                op['denominator']
            )
        except ZeroDivisionError as e:
            return UNIDEFINED
        else:
            op['result'] = value
            result = json.dumps(op)
            handle.seek(0)
            handle.write(result)
            return value
        finally:
            handle.close()
    

    相关文章

      网友评论

          本文标题:用pythonic方式来思考(3)

          本文链接:https://www.haomeiwen.com/subject/zjanlftx.html