zoukankan      html  css  js  c++  java
  • 【Python】《Effective Python》 读书笔记 (一)

    # -*- coding: utf-8 -*-
    
    from datetime import datetime
    from time import sleep
    from urllib.parse import parse_qs
    import json
    
    
    def example_1():
        """
        确认自己所用的Python版本
        * Python3 和 Python2 不兼容
        :return:
        """
        pass
    
    
    def example_2():
        """
        遵循PEP8风格指南
        * 不要通过检测长度的方法, 如 if len(somelist) == 0, 而是 if not somelist
        * 引入模块时, 应使用绝对名称, 而不是相对名称,如 from bar import foo 而不是
        import foo.
        * 如果一定要用相对名称, 就采用明确写法 from . import foo
        :return:
        """
        pass
    
    
    def example_3():
        """
        了解bytes,str和unicode的区别
        * Python3, bytes 包含原始8位值, str的实例包含Unicode字符
        * Python2, str 包含原始8位值, 而Unicode的实例包含Unicode字符
        * Python3的str实例 和Python的Unicode实例都没有和特定的二进制编码形式相关联
        :return:
        """
        pass
    
    
    def example_4():
        """
        用辅助函数来取代复杂的表达式
        :return:
        """
        my_values = parse_qs("red=5&blue=0&green=", keep_blank_values=True)
        print(my_values)
        # 如果键的值是空就返回0
        green = my_values.get("green", [''])[0] or 0
        print(green)  # 输出 0
        pass
    
    
    def example_5():
        """
        了解切割序列的方法
        :return:
        """
        a = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
        print(a[2:])  # 输出 ['c', 'd', 'e', 'f', 'g']
    
    
    def example_6():
        """
        在单次切片操作内, 不要同时指定start、end 和 stride(步进值)
        * 如果非要用stride, 尽量采用负值(或考虑itertools的islide方法)
        :return:
        """
        a = ['rad', 'orange', 'yellow', 'green', 'blue', 'purple']
        odds = a[::2]  # 表示从头部开始, 每两个元素选取一个, 如果是负号则是从尾部开始
        events = a[1::2]
        print(odds)  # 偶数索引
        print(events)  # 奇数索引
    
        x = b'mongoose'
        y = x[::-1]  # 字符反转技巧, 注意仅对ASCII字有用, UTF-8等无法奏效
        print(y)
    
    
    def example_7():
        """
        用列表推导来取代map和filter
        :return:
        """
        a = [1, 2, 3, 4, 5]
        print([x ** 2 for x in a])  # 列表推导表达更清晰
        print(list(map(lambda x: x ** 2, a)))
    
        even_squares = [x ** 2 for x in a if x % 2 == 0]
        print(even_squares)
        alt = map(lambda x: x ** 2, filter(lambda x: x % 2 == 0, a))
        print(list(alt))
    
    
    def example_8():
        """
        不要使用含有两个以上表达式的列表推导
        * 因为难以理解
        :return:
        """
        pass
    
    
    def example_9():
        """
        用生成器表达式来改写数据量较大的列表推导
        :return:
        """
        value = [len(x) for x in open('leecode.py')]  # 问题数据量大,内存激增
        print(value)
        it = (len(x) for x in open('leecode.py'))  # 改用生产器, 返回可迭代对象, 但注意迭代器有状态,仅能迭代一轮
        while True:
            try:
                x = next(it)
                print(x)
            except StopIteration:
                break
    
    
    def example_10():
        """
        尽量用enumerate来取代range
        * 下标和序列元素都能一次获取
        :return:
        """
        flavor_list = ['vanilla', 'chocolate', 'pecan', 'strawberry']
        for i, flavor in enumerate(flavor_list, 1):
            print("%d: %s" % (i + 1, flavor))
    
    
    def example_11():
        """
        用zip函数同时遍历两个迭代器
        * 比如两个list中的元素是一对一的关系
        :return:
        """
        names = ['Cecilia', 'Lise', 'Marie']
        letters = [len(n) for n in names]
    
        longest_name = None
        max_letters = 0
    
        for name, count in zip(names, letters):
            if count > max_letters:
                longest_name = name
                max_letters = count
        print(longest_name)
    
    
    def example_12():
        """
        不要在for和while循环后面写else块
        * Python可以这样做, 但是你不要这样做
        :return:
        """
        pass
    
    
    def example_13():
        """
        合理利用try/except/else/finally结构中的每个代码块
        :return:
        """
        UNDEFINED = object()
    
        def divide_json(path):
            handle = open(path, 'r+')
            try:
                data = handle.read()
                op = json.load(data)
                value = (op['numerator'], op['denominator'])
            except ZeroDivisionError as e:
                return UNDEFINED
            else:
                op['result'] = value
                result = json.dumps(op)
                handle.seek(0)
                handle.write(result)
                return value
            finally:
                handle.close()
    
    
    def example_14():
        """
        尽量用异常来表示特殊情况, 而不用返回None
        * 容易让调用者写出错误的代码,到底是程序异常的None? 还是自己数据的不合理?
         一个例子就是除法, 除数为0
        * 解决办法之一: 使用元祖,一个放数据,一个放成功状态(但是调用者可以用_忽略不去检测,也是比较尴尬)
        * 最好的解决就是抛异常给上一级
        :return:
        """
    
    
    def example_15():
        """
        了解如何在闭包中使用外围作用域中的变量
        * 获取闭包内的数据, 使用nonlocal关键字(Python2不支持,但是有解决)
        :return:
        """
        pass
    
    
    def example_16():
        """
        考虑用生成器来改写直接返回列表的函数
        * yield 关键字
        :return:
        """
    
        def index_words_iter(text):
            if text:
                yield 0
            for index, letter in enumerate(text):
                if letter == ' ':
                    yield index + 1
    
        text = 'apple pink origin'
        result = list(index_words_iter(text))
        print(result)
    
    
    def example_17():
        """
        在参数上面迭代时,要多加小心
        * 问题时迭代器迭代一次
        * 列表推导数据量大时, 内存激增
        * 解决一: 使用lambda, 每次都能产生新的迭代器
        * 最佳解决: 建立对象, 使用__iter__ 内置函数
        :return:
        """
        pass
    
    
    def example_18():
        """
        用数量可变的位置参数减少视觉杂讯
        :return:
        """
    
        def log(message, *values):
            if not values:
                print(message)
            else:
                values_str = ', '.join(str(x) for x in values)
                print("%s: %s" % (message, values_str))
    
        favorites = [7, 17, 99]
        log("Favorite colors", *favorites)  # 列表加上*号, Python 会把列表里的元素视为位置参数
    
    
    def example_19():
        """
        用关键字参数来表达可选行为
        * 一个除法函数, 谁是除数? 谁是被除数?
        :return:
        """
        pass
    
    
    def example_20():
        """
         用None和文档字符串来描述具有动态默认值的参数
        :return:
        """
    
        def log(message, when=None):
            """
    
            :param message:
            :param when: datetime of when the message occurred.
                        Default to the present time.
            :return:
            """
            when = datetime.now() if when is None else when
            print('%s: %s' % (when, message))
    
        log('Hi there!')
        sleep(0.1)
        log('Hi again!')
    
    
    def example_21():
        """
        只能用以关键字形式指定的参数来确保代码清晰
        :return:
        """
    
        def safe_division(number, divisor, ignore_overflow=False, ignore_zero_division=False):
            try:
                return number / divisor
            except OverflowError:
                if ignore_overflow:
                    return 0
                else:
                    raise
            except ZeroDivisionError:
                if ignore_zero_division:
                    return float("inf")
                else:
                    raise
    
        # 调用者可以根据自己的具体需要, 用关键字来覆盖Boolean标志的默认值, 以便跳过相关的错误
        safe_division(1, 10 ** 500, ignore_overflow=True)
        safe_division(1, 0, ignore_zero_division=True)
    
    
    if __name__ == '__main__':
        example_18()
        # example_5()
        # example_20()
        # example_21()
    
    
    “年轻时,我没受过多少系统教育,但什么书都读。读得最多的是诗,包括烂诗,我坚信烂诗早晚会让我邂逅好诗。” by. 马尔克斯
  • 相关阅读:
    Ubuntu+Windows双系统升级Windows启动项消失恢复
    day19 Servlet Filter
    day17 dbutils 和 jdbc 多表操作
    day16 事务
    day15 分页及 JDBC 大数据的处理
    day14 JDBC
    day13 MySQL 及数据库相关
    Windows系统中完全卸载MySQL数据库,实现重装
    Elasticsearch 6.5.4 安装IK Analysis插件
    js 常用功能
  • 原文地址:https://www.cnblogs.com/jzsg/p/11308074.html
Copyright © 2011-2022 走看看