张凯朝

张凯朝的博客

他的个人主页  他的博客

Dive Into Python 学习笔记点滴

张凯朝  2010年01月26日 星期二 22:48 | 1634次浏览 | 2条评论

Dive Into Python 学习笔记点滴

Dive Into Python notes
=====================================
学习的是啄木鸟社区翻译的 5.4b 版本

20010,01,18

1. tuple 没有方法。不能改变,适合做常量。提供给仅遍历使用的时候效率比 list 高。

2. list 的 extend 方法比 + 方法效率高。

3. callable 判断一个对象是否可调用,可调用对象包括函数、类方法,甚至类自身。

4. getattr 作为一个分发者::

    import statsout
    def output(data, format="text"):
        output_function = getattr(statsout, "output_%s" % format, \
                statsout.output_text)    # 最后一个参数是缺省值
        return output_function(data)

5. 可以使用映射表达式过滤列表重复元素::

    li = ["a", "xx", "yy", "b", "a", "c", "zz", "yy"]
    new_li = [elem for elem in li if li.count(elem) == 1]

6. and-or 技巧失效场合的补救::

    a = ""
    b = "second"
    (1 and [a] or [b])[0]

    注:[""] 列表有一个元素,所以它能保证 [a] 为真。虽然这个技巧可以使用 if 语句来替代,但是在某些情况下 if 是不允许使用的,比如在 lambda 函数中。

7. 不带参数的 split 按照空白进行分割。在这里,空格、回车和制表符等都将被当成空白处理。然后再用空格的 join 方法将其连接,就可以得到统一的空格。例如::

    s = "This  is\na\ttest!"
    new_s = " ".join(s.split())

8. 可以使用 == None 或者 is None 进行比较,但是 is None 更快。

9. 字符串的 ljust 方法用空格填充字符串以符合指定的长度。如果指定的长度小于字符串的长度,ljust 将简单地返回未变化的字符串。

10. update 方法是一个字典复制器:它把一个字典中的键和值全部拷贝到另一个字典。这个操作并不事先清空目标字典,如果一些键在目标字典中已经存在,则它们将被覆盖,那些键名在目标字典中不存在的则不改变。应该把 update 看作是合并函数,而不是复制函数。

11. __init__ 在类的实例创建后被立即调用。
每个类方法的第一个参数,包括 __init__ ,都是指向类的当前实例的引用。按照习惯这个参数总是被称为 self 。在 __init__ 方法中,self 指向新创建的对象;在其他方法中,它指向方法被调用的类实例。

12. 专用类方法
__getitem__ :只要定义了该方法,任何类都可以像字典一样保存键值。
__setitem__ :只要定义了该方法,任何类都可以表现得像序列。
__delitem__ :在调用 del instance[key] 时调用。
__repr__ :当调用 repr(instance) 时被调用。
__cmp__ :当使用 == 来比较类的时候被教用。
__len__ :在调用 len(instance) 时被调用。
__call__ :定义了这个方法的类将让这个类表现得像一个函数,允许你直接调用一个类实例。

13. 类属性
类属性紧跟在类定义之后定义,数据属性定义在 __init__ 方法中。
类属性可以作为类级别的常量来使用,但是它们不是真正的常量。Python 中没有常量。
类属性既可以通过直接对类的引用,也可以通过对类的任意实例的引用来使用。
可以通过各种方式改变类属性。

    class Counter:
        count = 0
        def __init__(self):
            self.__class__.count += 1
    print Counter.count    # -> 0
    cl = Counter()
    print c1.count    # -> 1
    print Counter.count    # -> 1
    c2 = Counter()
    print c2.count    # -> 2
    print Counter.count    # -> 2

14. 使用字典的 items 方法得到该字典键值对的元组所组成的序列,是处理字典数据元素的一个比较好的办法。

    for (k, v) in dict.items()

比如使用 join 来打印 list ::

    import os
    print "\n".join(["%s=%s" % (k, v)
            for k, v in os.environ.items()])

15. os.path 中的 expanduser 方法将对使用 ~ 来表示当前用户根目录的路进进行扩展。在任何平台上,只要用户拥有一个根目录,它就会有效,像 Windows、Unix 和 Mac OS X,但在 Mac OS 上无效。

    home_dir = os.path.expanduser("~")

16. os.path 中的 normcase 方法将根据操作系统的缺省值对大小写进行标准化处理。normcase 是一个有用的函数,用于对大小写不敏感操作系统的一个补充,这种操作系统认为 mahadeva.mp3 和 和 mahadeva.MP3 是同一个文件。例如,在 Windows 和 Mac OS 下,normcase 将把整个文件名转换为小写字母串;而在 Unix 兼容的系统下,它将返回未作修改的文件名。

17. 使用 glob 列出目录 ::

    >>> import glob
    >>> glob.glob("C:\\music\\*\\*.mp3")
    ['C:\\music\\a\\a1.mp3',
    'C:\\music\\a\\a2.mp3',
    'C:\\music\\b\\b1.mp3',
    'C:\\music\\b\\b2.mp3']

18. 原始字符串:为了避免反斜线灾难,你可以利用所谓的“原始字符串”,只要为字符串添加一个前缀 r 就可以了。这将告诉 Python ,字符串中的所有字符都不转义。推荐处理正则表达式的时候使用原始字符串;否则事情会很快变得混乱。

19. 如果一个问题可以使用字符串处理也可以使用序列处理,那么最好选择序列,因为 Python 在处理序列方面效率更高一些。

20. locals 和 globals 内置函数:

1) 都是字典;
2) 局部名字空间可以通过内置的 locals 函数来访问,全局(模块级别)名字空间可以通过内置的 globals 函数来访问;
3) 局部(函数)名字空间产生了变化则 locals 函数 和 globals 函数返回都产生相应的变化,而 globals 更令人兴奋,模块的名字空间不仅仅包括了模块级的变量和常量,还包括了所有在模块中定义的函数和类,并且还包括了任何被导入到模块中的东西,当然 局部(函数)名字空间也包含了任何被导入到函数中的东西;
4) locals 函数返回的是局部名字空间的一个拷贝,所以对它进行改变对局部名字空间中的变量值并无影响,但 globals 函数返回实际的全局名字空间,而不是一个拷贝,故与 locals 函数的行为完全相反,对 globals 所返回的任何改动都将直接影响到全局变量;
5) 在调用 locals 函数时有一点性能上的问题,这是由于 locals 创建了局部名字空间的一个拷贝引起的。

21. Python 处理 list 比字符串快的原因是:
list 是可变的,但字符串是不可变的。这就是说向 list 进行追加只是增加元素和修改索引。因为字符串在创建之后不能被修改,像 s = s + newpiece 这样的代码将会从原值和新片断的连接结果中创建一个全新的字符串,然后丢弃原来的字符串。这样就需要大量昂贵的内存管理,并且随着字符串变长,所需要的开销也在增长。所以在一个循环中执行 s = s + newpiece 非常不好。用技术术语来说,向一个 list 追加 n 个项的代价为 O(n) ,而向一个字符串追加 n 个项的代价是 O(n^2) 。

22. 编译正则表达式
在需要多次使用同一个正则表达式的情况下,应该将它进行编译以获得一个 pattern 对象,然后直接调用这个 pattern 对象的方法。

23. 动态导入模块
使用 __import__ 内置函数可以动态地导入模块。如 sys = __import__("sys")

24. 生成器
第一次调用生成器对象的 next() 方法,将执行生成器对象中第一个 yield 语句之前的所有代码,然后返回生产(yield)出来的值。接下来不断调用生成器对象的 next() 方法,将从上次离开的位置重新开始并继续下去直到又一次遇到 yield 语句。

25. 内置计时器
timeit 模块定义了接收两个参数的 Timer 类。两个参数都是字符串。第一个参数是你要即使的语句,第二个参数是为第一个参数语句构建环境的导入语句。从内部讲, timeit 构建起一个独立的虚拟环境,手工地执行建立语句,然后手工地编译和执行被计时。
只要有了 Timer 对象,最简单的事就是调用 timeit() ,它调用你的函数一百万次并返回所耗费的秒数。
Timer 对象的另一个主要方法是 repeat() ,它接收两个可选参数。第一个参数是重复整个测试的次数,第二个参数是每个测试中调用被计时语句的次数。两个参数都是可选的,它们的默认值分别是 3 和 1000000 。repeat() 方法返回以秒记录的每个测试循环的耗时序列。
repeat() 返回的时间序列,由于后台进程或者其他 Python 解释器以外的因素的影响,将使得计时器得到的耗时延长,最好的处理是取最小值而丢弃其他结果。
timeit 模块只有在你知道哪段代码需要优化时使用。如果你又一个很大的 Python 程序并且不知道你的性能问题所在,查看 hotshot 模块。

26. min 和 max 内置函数

27. isalpha 内置函数,检查一个字符串中是否只包含字母。

评论

我的评论:

发表评论

请 登录 后发表评论。还没有在Zeuux哲思注册吗?现在 注册 !
张凯朝

回复 张凯朝  2010年01月27日 星期三 22:04

呵呵
我现在觉得还是 ruby 比较有希望一点。。。
所以在学 ruby 中
Python 和 Ruby 的中文书籍都严重滞后,真的是很艰苦。。。

0条回复

邓泉

回复 邓泉  2010年01月27日 星期三 12:03

呵呵,我也刚开始看这本书,之前看了a byt of python 都看了en版的,为了提高英文水平,不过看的有点艰苦,呵呵

0条回复

暂时没有评论

Zeuux © 2024

京ICP备05028076号