Home - noonecare/python GitHub Wiki

介绍 python 中重要的概念。 主要包括:

1. 开发中好的实践

1.1 测试

1.2 IDE

1.3 文档

2. 容易误解的语法,比较有特点的语法

2.1 装饰器/decorator

2.2 名称空间

  • python 有四种方式可以引入 namespace
    • import
    • def
    • class
    • 声明变量, 比如 a = 3, 会引入 a 变量。 global a ,会引入全局变量 a。
    • __init__.py 能把目录变成 package 也可以认为是引入了 namespace。常常会在 init.py 文件中写 import XXX as YY 语句。
  • 引用包的路径
    • .pth 文件
    • 解释器的 site-packages 目录
    • PYTHONPATH 环境变量
  • 包内引用
    • 包内引用 module,使用 from . import 的形式, from . 会从当前路径中找 module 引入。

2.3 reflect

  • __dict__
  • dir()

2.3 Descriptor(Key Word: Access Interception)

  • 新式类,旧式类
    • 继承之 object 的类称为新式类,python3 中所有类都是新式类(说明 python3 是纯粹的面向对象语言),Python2 中有旧式类(不是新式类的类),说明 python2 不是纯粹的面向对象语言。
  • Attribute Access
    • 存在 object a, 执行 a.foo 时,实际是上执行 a.__getattribute__("foo"), 如果__getattribute__ 找不到 "foo", 就会调用 a.__getattr__("foo") ,如果 __getattr__ 找不到 "foo", __getattr__ 会报异常。
    • __getattr__ method 可以被重写,改变默认行为。__getattribute__ 也可以被重写,不过__getattribute__ 几乎没有人去重写它, 因为 __getattribute__ 就是 python access attribute 的机制。
    • __getattribute__ 的详细机制如下:
      • 如果 a 属于 type 类型
        • 查找 a 中是否有名为 "foo" 的 data descriptor, 如果有返回这个 data descriptor 的值,如果没有继续搜索。
        • 查看 a __dict__ 中是否有 "foo" 属性,如果有返回这个属性的值;如果没有继续搜索。
        • 查看 a 中是否有名为 "foo" 的 non data descriptor, 如果有返回这个 non data descriptor 的值,如果没有继续搜索。
        • 沿着 a 的 mrb 属性解析路径,找 a 的 parent class, 对于 parent class 采用和查找 a 的属性一致的方式,查找 a 的 parent class 的属性。
        • 如果找遍 mrb 还找不到属性,就 raise AttributeError。
      • 如果 a 不属于 type 类型。
        • 查找 a 的 __dict__ 中是否有名为 “foo” 的属性,如果有,返回这个属性的值,如果没有,继续搜索。
        • 查找 type(a) 的 foo 属性, type(a) 属于 type 类型,按照刚才提到的搜索 type 的属性值的方式搜索 type(a) 的属性值。

2.4 Descriptor

  • descriptor 只能作为 class attribute 的值,不能作为 instance attribute 的值
  • class a 中定义了 __get__, __set__ method, a 的实例就是 data descriptor。
  • class a 中定义了 __get__ method, 没有定义 __set__ method, a 的实例就是 non-data descriptor。
  • descriptor(比如称为 d) 经常作为另一个 object(比如记为 o) 的 attribute 的 value(这就是常常说的 d descriptor attached to object o)。 调用 descriptor 时, 比如 o.d 时,实际执行的是 d.__get__(o)。
  • @property, @staticmethod, @classmethod 这三种 decorator 都是用 descriptor 和 decorator 的技术实现的。descriptor 也常常被称为 custom property。

2.5 GIL(Global Interpreter Lock)

  • python 中的线程必须和 python 解释器运行在同一个 CPU core 上(这就是 GIL),因此 GIL python 线程没法利用多核。
  • python 中进程不受 GIL 影响,可以利用多核。(在java 中线程就是进程。在python 以及操作系统中线程和进程不同,一个进程可以有多个线程, 线程没有独立的地址空间,进程有独立的地址空间。一个进程的变量,对于另外的进程不一定可见,这一点在多进程编程时要小心)
  • C Extension 也不受 GIL 影响,可以使用多核。

2.6 Managed Context(with 语句)

2.7 异常处理: finally 后面的语句,无论放生什么情况都一定会执行。

2.8 协程(coroutine)

  • coroutine 的特点是有多个 entrypoint, 有自己的状态,协程之间相互交错的执行。
  • python 协程非常好的教程。简单讲, 在 python 中协程是用 yield 写的, 协程的一个非常重要的方法是 send。协程非常适合用于实现 pipeline, finite state machine, Event handling 等等,具体看我推荐的教程。

2.9 函数语言特性(使得一些运算变得简洁)

  • 列表表达式
    • a = range(100); b = [a ** a for i in a]
  • lambda 表达式
    • lambda x: x + 1
  • map, reduce, filter 等函数
    • a = range(100); b = filter(lambda x: x > 50, a)

2.10 小技巧

  • 字符串前的 r, b, u 前缀

  • __file__ 变量

    • 表示当前文件的完整路径, 如果需要以当前源码所在的路径为基准,写相对路径,就会用到这个变量。
    • 比如写测试用例,测试数据和测试代码的相对路径是不变的,这时候,用 __file__ 来加载测试数据就非常方便。
  • slice list

    • a[-1] 表示 a list 的最后一个元素
    • a[m:n] 表示 a 中 m 到 n 个元素组成的 list
    • a[1] 表示 a 中第 2 个元素
    • zip(a, b), a list 和 b list 配对组成的 list
  • dict

    • update
    • 有 2-tuple 组成的 list 可以直接生成 dict, dict(zip(a, b)) 如果 a, b 是 list 的话。
    • del
  • enumerate 函数

    • for 循环,要索引,可以使用 enumerate 函数。
  • tuple 赋值: a, b = 1, 2

  • args, kwargs

  • 访问权限

    • _ 开头的变量以及方法,不应当直接访问。
    • __ 开头的变量以及方法( private ), 从外部访问时,比较麻烦,不要访问这样的变量。
  • __slot__ 减小内存占用

  • Cython: C Extension for Python

3.常用的一些包

python 简单,很大部分原因,就在于有现成的包可用(而且 python 的文档比 java/scala 要规范)。良好的编程规范,以及熟悉常用的包 比熟悉 python 中不常用的语法要重要。学习这些包时,重在理解概念。

  • webserver

  • 文件系统/目录

  • 数据分析: pandas

    • 数据的写入写出
      • read_csv, read_json, read_excel, read_sql 使得 pandas 读入带 schema 的数据非常方便。
      • to_csv, to_json, to_excel, to_sql 使得 pandas 把 DataFrame 写出非常方便。
      • DataFrame
        • Series
        • 单机版的 sql
        • map, apply method
  • 科学计算: numpy

  • 事件驱动: twisted

  • 读取配置文件: configparser

  • 读取命令行: argparser, 重要的概念有: 位置参数,可选参数,参数类型。

  • 记日志: logging

  • 爬虫:

    • urllib
    • requests
    • scrapy
  • 打包: setuptools

  • 调用外部程序: subprocess

  • 数据库

    • sqlite
    • mysql
    • hive/impala
  • 文本

  • 时间

  • 测试

  • Garbage Collection