Effective Python

第1章 用Pythonic方式来思考

  • be pythonic

  • 遵守pep8

  • python3有两种字符序列类型:bytes(原始的字节)和str(Unicode字符).

  • 在python3中需要用二进制方式读写文件时,要用wb和rb

  • 应该尽可能使用if/else表达式和辅助函数来使代码清晰

  • 不要在单次切片中同时指定start, end和stride.可以采用两步进行范围切割和步进切割.

  • 使用列表推导来代替map和filter

  • 不要在列表推导中使用两个以上的表达式.使用if和for语句代替.

  • 如果数据量很大,用生成器表达式来改写列表推导.生成器表达式会返回一个迭代器,然后可以用next来生成新值.

  • 如果需要同时使用list的索引和元素,最好使用enumerate替代range

  • 用zip函数同时遍历2个迭代器

  • 利用try/except/else/finally进行异常处理

第2章 函数

  • 尽量用异常来表示特殊情况,而不是None

  • python支持闭包,闭包是一种定义在某个作用域的函数,这种函数引用了那个作用域里的变量.

  • python的函数是一级对象,也就是可以直接引用,可以赋给变量,可以当成参数传给其他函数.

  • 函数中的局部变量不会影响外部作用域.如果需要获取闭包函数内的数据,应该使用nonlocal声明变量.如果使用nonlocal让代码变得复杂,应该将相关的函数封装成辅助类.

  • 如果函数返回列表,可以考虑用生成器改写,将return变为yield.

  • 如果需要在函数中多次迭代一个生成器,可以考虑把写一个容器,把__iter__方法实现为生成器.

  • 令函数接受可选的位置参数*args,能够使代码清晰.如果要把列表中的所有元素作为位置参数传入,就在列表前加上*.

  • 可选参数有两个问题,一个是过长的生成器作为参数会导致消耗大量内存,一个是不方便修改函数.

  • 可以用关键字参数表示函数可选的行为和默认值.参数的默认值会在模块加载的时候求出.因此不要在参数默认值中创建[]或{}等动态的值.解决方法是把默认值设为None,并在docstring中具体解释.

  • 可以在定义函数的时候用*来分隔位置参数和关键字参数(只能以关键字指定的参数)

第3章 类与继承

  • 当数据结构比较复杂时,尽量用辅助类来维护程序的状态,而不要用字典和元组.

  • 类似sort的key参数可以接受一个函数,这称挂钩(hook)函数.

  • 简单的接口应该接受函数而不是类的实例,因为函数是一级对象.

  • 如果要用函数保存状态,应该定义新的类并实现__call__方法

  • 通过@classmethod可以构造多态的类的对象.

  • 较复杂的继承体系中,如果仍让子类直接调用父类的__init__,会出现很多意想不到的行为,因此建议用super初始化父类.

  • mix-iin是一种只定义了其他类可能需要提供的一套附加方法的小型类.只在使用mix-in组件类时进行多重继承.

  • Python类的属性只有public和private.一般还会用单个下划线开头来习惯性命名protected.

  • private属性是开头至少有两个下划线,结尾至多有一个下划线的属性.python对于__private_name的保存机制实际上是_ClassName__private_name.因此可以通过这种方式访问所有private属性.

  • 应该多用前者,少用后者.

  • 如果要定制简单子类,可以直接从python的容器类型继承.否则可以继承collections.abc中的抽象基类以实现自定义的容器类型.

第4章 元类及属性

  • 用纯属性取代get和set方法

  • 如果想要使用get和set,应该使用@property修饰器的getter和setter.它的缺点是不便于复用.

  • 描述符可以把同一套逻辑运用在类中的不同属性上面.

  • WeakKeyDictionary可以保证描述符类不会泄露内存

第5章 并发及并行

  • 并发(concurrency)是指计算机通过迅速切换看似在同一时间做很多不同的事.并行(parallelism)则是指计算机确实在同一时间做很多不同的事.

  • subprocess用于与外部进程交互.

  • Python解释器能平行地运行多条子进程.

  • GIL确保了字节码解释器的协调性,但也带来了同一时刻只能进行一条线程的负面影响.因此Python的多线程适用于处理阻塞式的I/O操作,而不是平行计算.

  • Python多线程同样需要使用Lock来防止数据竞争,因为解释器可能会在线程的任意时刻暂停它们.

  • 用queue.QUeue来协调各线程之间的工作.它解决了并发式管道存在的问题.

  • 线程存在的问题是:代码复杂,需要占用大量内存(大约8mb),启动时的开销比较大.协程可以避免这些问题.

  • 协程的工作原理是:每当生成器函数执行到yield表达式时,消耗生成器的那段代码,就通过send方法给生成器回传一个值.

  • concurrent.futures会以子进程的形式平行地运行多个解释器,从而令python能够利用多核心CPU来提升速度.这种做法适用于较为孤立且数据利用率高的任务.

第6章 内置模块

  • functools.wraps可以定义函数修饰器,用于在函数执行之前以及执行完毕之后分别运行一些附加代码.可以实现约束语义,调试程序,注册函数等目标.

  • contextlib模块可以使自己编写的对象和函数支持with语句.

  • python的pickle模块能将python对象序列化为字节流,也能将这些字节反序列化为python对象.但是这种序列化数据采用的是不安全的格式,如果其中有恶意信息,在反序列化时可能对程序造成损害.Json数据则是安全的.

  • copyreg能使pickle变得可靠.

  • 使用datetime而不是time来处理本地时间

  • 使用内置的算法和数据结构,例如collections.deque双向队列,collections.OrderedDict有序字典,collections.defaultdict带有默认值的字典,heapq堆,bisect二分查找,itertools处理迭代器.

  • 在重视精确度的场合,应该使用decimal

第7章 协作开发

  • 为每个函数,类和模块编写docstring.

  • 用包来安排模块,并提供稳固的API.

  • 为自编的模块定义根异常,以便将调用者与API相隔离.

第8章 部署

  • 可以用模块级别的代码来配置不同的部署环境

  • 通过repr来输出调试信息

  • 用unittest来测试代码

  • pdb模块的set_trace()可以让程序在执行到某一行的时候暂停,用于调试.

  • 利用cProfile来分析每个模块的性能,然后再优化.

  • 用tarcemalloc来掌握内存的使用及泄露情况.

《Effective Python:编写高质量Python代码的59个有效方法》读书笔记(完结)的更多相关文章

  1. Effective Python 编写高质量Python代码的59个有效方法

    Effective Python 编写高质量Python代码的59个有效方法

  2. 编写高质量JavaScript代码的68个有效方法

    简介: <Effective JavaScript:编写高质量JavaScript代码的68个有效方法>共分为7章,分别涵盖JavaScript的不同主题.第1章主要讲述最基本的主题,如版 ...

  3. 编写高质量JS代码的68个有效方法(八)

    [20141227]编写高质量JS代码的68个有效方法(八) *:first-child { margin-top: 0 !important; } body>*:last-child { ma ...

  4. 编写高质量JS代码的68个有效方法(七)

    [20141220]编写高质量JS代码的68个有效方法(七) *:first-child { margin-top: 0 !important; } body>*:last-child { ma ...

  5. 编写高质量JS代码的68个有效方法(六)

    [20141213]编写高质量JS代码的68个有效方法(六) *:first-child { margin-top: 0 !important; } body>*:last-child { ma ...

  6. 编写高质量JS代码的68个有效方法(四)

    [20141129]编写高质量JS代码的68个有效方法(四) *:first-child { margin-top: 0 !important; } body>*:last-child { ma ...

  7. 编写高质量JS代码的68个有效方法(三)

    [20141030]编写高质量JS代码的68个有效方法(三) *:first-child { margin-top: 0 !important; } body>*:last-child { ma ...

  8. 编写高质量JS代码的68个有效方法(二)

    [20141011]编写高质量JS代码的68个有效方法(二) *:first-child { margin-top: 0 !important; } body>*:last-child { ma ...

  9. JavaScript手札:《编写高质量JS代码的68个有效方法》(一)(1~5)

    编写高质量JS代码的68个有效方法(一) *:first-child { margin-top: 0 !important; } body>*:last-child { margin-botto ...

  10. 编写高质量JS代码的68个有效方法(十三)

    No.61.不要阻塞I/O事件队列 Tips: 异步API使用回调函数来延缓处理代价高昂的操作以避免阻塞主应用程序 JavaScript并发的接收事件,但会使用一个事件队列按序地处理事件处理程序 在应 ...

随机推荐

  1. javascript面向对象的一些写法

    因为有闭包,能返回函数,所以针对于面向对象的封装,继承,多态三个特性实现,很舒服. 代码如下: <!DOCTYPE html> <html> <head> < ...

  2. 【转】Windows Server 2008 R2怎样设置自动登陆

    Windows Server 2008 R2是一款服务器操作系统,提升了虚拟化.系统管理弹性.网络存取方式,以及信息安全等领域的应用,Windows Server 2008 R2也是第一个只提供64位 ...

  3. codevs 1191 数轴染色 区间更新加延迟标记

    题目描述 Description 在一条数轴上有N个点,分别是1-N.一开始所有的点都被染成黑色.接着我们进行M次操作,第i次操作将[Li,Ri]这些点染成白色.请输出每个操作执行后剩余黑色点的个数. ...

  4. WPF基础学习笔记整理 (七) Binding绑定

    基础知识: 数据绑定是一种关系,该关系告诉WPF从源对象提取一些信息,并用这些信息设置目标对象的属性:目标对象始终是依赖属性,而源对象则可以是任何内容. BindingOperations类,提供静态 ...

  5. IntelliJ IDE 开发Java GUI 入门

    j主要对java 的GUI相关知识进行简单的介绍和总结,整个博客按照创建一个java GUI的顺序进行介绍,期间穿插讲解用到的java Swing的布局.控件等相关知识.本博客所进行的讲解及工程的创建 ...

  6. npm 安装文件 运行报错 %1 is not a valid Win32 application

    安装了那个模板出了错报这样的错误 “%1 is not a valid Win32 application” 你就除那个模板新安装. 如下例: 运行 npm install -g @angular/c ...

  7. 搭建Eclipse+ADT+Android SDK 安卓开发环境

    安装JDK 请看JDK环境搭建 即可. 安装Eclipse Eclipse 是一个开放源代码的.基于Java的可扩展开发平台.就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境.幸运 ...

  8. python-day28--logging模块

    1.默认情况下Python的logging模块将日志打印到了标准输出中,且只显示了大于等于WARNING级别的日志,这说明默认的日志级别设置为WARNING(日志级别等级CRITICAL > E ...

  9. OncePerRequestFilter的作用

    在spring中,filter都默认继承OncePerRequestFilter,但为什么要这样呢? OncePerRequestFilter顾名思义,他能够确保在一次请求只通过一次filter,而不 ...

  10. java 判断字符串IP合法性以及获取IP的数值形式

    /** * 计算传入的IP地址的数字IP*/ public static long getIpNum(String ip) { long ipNum = 0; if (StringUtils.isNo ...