0%

Python note

更新汇总一些关于python的小技巧

  1. if A is not None 效率要比 if A 要一些,如果 A 是 list,那么 if A 等同于 if len(A) 及 if A is not None。更多解释见if-a-vs-if-a-is-not-none

  2. 如果你需要使用类似 if classname 之类的条件判断可以在类中定义__nonzero__方法(3.x用__bool__)来返回True或False,如果这个方法在类中没有定义,len()会被调用,只要不是零就会返回True,如果两个都没有定义那么类的实例if instance 都是True。

  3. 递归遍历目录时经常会用到os.walk(还有os.path.walk,但推荐前者,因为兼容python3),基本形式是

    for root, dirs, files in os.walk(".")

    那么每一个循环的结果是什么呢?
    假设目录是:
    .
    ..
    a-dir/
    b-dir/
    t.txt
    那么输出就是:
    第一个循环
    root .
    dirs [a-dir, b-dir]
    files [t.txt]
    第二个循环
    root ./a-dir
    dirs []
    files []
    结合官网文档可以知道,每一个循环是由str类型的root路径,root路径下的文件夹dirs和files组成,并且dirs和files都是只在当前root下的;接着的循环会进入第一个文件夹,同样root被替换成./a-dir,之后都是一样的list类型的dirs和files。
    故可以这样遍历目录所有文件:

    for root, dirs, files in os.walk("."):
        for f in files:
            print os.path.join(root, f)
  4. 注意list()生成的新对象并不是完全的深拷贝,考虑如下代码:
    代码来自deep copy list

    >>> a = [[1, 2, 3], [4, 5, 6]]
    >>> b = list(a)
    >>> a
    [[1, 2, 3], [4, 5, 6]]
    >>> b
    [[1, 2, 3], [4, 5, 6]]
    >>> a[0][1] = 10
    >>> a
    [[1, 10, 3], [4, 5, 6]]
    >>> b   # b changes too -> Not a deepcopy.
    [[1, 10, 3], [4, 5, 6]]
    Now see the deepcopy operation
    
    >>> b = copy.deepcopy(a)
    >>> a
    [[1, 10, 3], [4, 5, 6]]
    >>> b
    [[1, 10, 3], [4, 5, 6]]
    >>> a[0][1] = 9
    >>> a
    [[1, 9, 3], [4, 5, 6]]
    >>> b    # b doesn't change -> Deep Copy
    [[1, 10, 3], [4, 5, 6]]

    事实上list()确实生成了新对象(可以用id查看),但是对于里面的嵌套list对象仅仅是浅拷贝,如果是数字这样的不可变对象则是完全的复制,如 a = [1,2,3,4] b = list(a)