OReilly.Learning.Python.3rd.Edition.Oct.2007


                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                7 / 21 / 2008
    import this    显示Python的设计原则
    source(*.py) ---> bytecode(*.pyc) ---> PVM
    若是python在.py所在目录有写权限,则执行完会产生.pyc文件,下次执行时会直接使用.pyc文件,除非.py文件被修改了(通过时间戳比较,类似于make程序^^);若是没有写权限,则.pyc存在于内存中
    .pyc文件可以加快执行速度
    可以将所有.py文件翻译为.pyc文件后打包发布,Python乐意使用.pyc文件,可以加快执行速度
    只保存被import的文件的字节码;嵌套的import的文件也会被执行并生成字节码,只有top-level文件的字节码不保存
    将python程序做成二进制文件实际上是将程序的字节码文件、PVM和支持库打包。因为python程序是在PVM上运行的,所以不像传统语言的二进制文件运行那么快,并且二进制文件要大一些
    所有以.py结尾的源文件都可看作是module
    import会找到文件、将其转换为字节码文件(import会导致生成.pyc文件)、最后执行。import的目标优先是.pyc文件。嵌套的import的文件也会被执行并生成字节码,只有top-level文件的字节码不保存
    import最终会执行module,执行module时生成attributes
    reload处理的module应该已经import过
    reload是函数,而import是statement。reload返回载入的module对象的一个描述
    在一个进程中,若是.py文件修改过,则reload会重新加载;而import会使用旧的.pyc文件(内存中),因为import代价比较大
    attribute是一个绑定到特定对象的变量名,例如函数名
    from复制模块的attribute,这样它们就成了调用者的变量
    execfile('module.py')会加载执行代码,但是它更像将代码粘贴到调用点执行,而不是import模块;因此,它可能会潜在地修改调用者的变量
    module search path = stardard dirs + PYTHONPATH => sys.path
    在Python中的赋值会产生对对象的引用,而不是copy
    bytecode + PVM + support files = frozen binary
    module(.py)   ---   namespace   ---   attributes
                                   ---> import ---> execute
7 / 23 / 2008
    Python中所有东西都是对象,小到简单数据类型,大到程序代码
    Python程序中处理的任何事物都是一种对象
    Python的类型是动态的,它自动跟踪类型而不是使用声明;但它也是强类型的,在特定类型对象上只能进行限定的操作
    Python中没有类型声明,表达式决定了对象的类型
    import math
    import random
    s[:]     top-level复制
    number、string、tuple是immutalbe的,而list和dictionary是mutable
    string对象有自己的方法,不管方法名字怎样,string对象都是immutable的,例如replace()
    s.find('str')
    s.replace('s', 'r')
    s.split('delimiter')
    s.upper()
    s.isalpha()
    s.rstrip()
    ord('c')
    re
    list + listx    生成新的list,不会改变原有的list
    list.append    改变原有的list
    list.pop(index)
    list.sort()
    list.reverse()
    虽然list的大小不固定,但是不允许越界访问
    list是mutable的,而且元素类型可以不同。list的元素可以变化,其本身也可以增大或缩小。虽然list的大小没有限制,但是当前list对象的大小是固定的,要增大只能通过append方法,越界赋值是不允许的
    [expression looping-construct]   =>  list comprehension
    Python中,interger的精度同C中的long,而floating-point的精度同C中的double;python会在integer溢出时将其自动转换为long型
    在内部,复数以floating-point对的形式出现
    Python3.0中,integet会同long统一成没有精度限制的integer
    在python中,变量不需要提前声明,但是在使用前必须初始化
    Python支持位操作,但是在python中推荐使用其他方法对信息进行存储
    在Python中,不要将一串数字以0开头,它会被看作是8进制数,会导致行为不像你想的那样
    dictionary可以自由扩充,是mutable的,不像list那样有越界限制,但是若是查找时key不存在也会报错
    d.keys()
    d.has_key('key')
    setX &/|/- setY      集合类型
    decimal对象可以指定固定精度  import decimal
    None
    type可以检测对象类型,但是不推荐这样做,会限制处理范围,失去python的动态类型处理的特点
    Python会自动回收内存,具有垃圾回收机制
    Python将内置函数放于模块__builtin__中
    通过将一个序列或者其他可遍历对象传给函数set可以创建一个set对象
    True和False是bool类型的实例,即它们也是对象
    赋值操作实际上是将对象绑定到变量
    raw string的最后一个字符不能是\,可以如此表示  r'str''\\'
    string.Template('str')
    template.substitute(key=value)
    template.substitute(dict)
    string.maketrans
    str.translate
    dict.copy             top-level复制
    deepcopy(dict)        完全复制
    dict.get(key)    若是不存在就返回NULL,而不会报错
    print最后一个参数的后面添加‘,’,则下一个print语句将在同一行继续输出
    sequence unpacking中变量的数量与目标的数量应该一致
    exec执行语句,eval计算表达式的值
    input = eval(raw_input(...))
    zip(seq1, seq2, ...) 创建适合并行遍历的新的序列
    函数可以返回多个值,例如将它们保存到tuple/list中返回
    在函数起始部分的字符串会被看作是docstring,可以通过func.__doc__访问,或者help(func)
    任何时候,变量保存的都是对象引用,可以通过引用改动mutable对象,或者改变引用
    位置参数
    关键字参数    虽然输入多了一些,但是可以清晰每个参数的作用,而且不用受参数顺序限制
    缺省参数
    关键字参数可以和缺省参数一起使用;关键字参数也可以与位置参数一起使用,但是调用时位置参数要在关键字参数前面,否则解释器不知道如何匹配
    *参数、**参数
    定义或者调用函数时通过使用*或者**参数可以容易地传递元组或者词典
    python的源文件可以通过编码使用ASCII以外的字符集,最好的方法是在#!行后面用一个特殊的注释行来定义字符集:
         # -*- coding: encoding -*-
根据这个声明,python会尝试将文件中的字符编码转为encoding编码,并且它尽可能的将指定的编码直接写成unicode文本。在python库参考手册中codecs部份可以找到可用的编码列表;根据个人经验,推荐使用cp-936或utf-8处理中文。
    使用UTF-8内码(无论是用标记还是编码声明),可以在字符串和注释中使用世界上的大部分语言。标志符中不能使用非ASCII字符集。
    *表示收集剩余的位置参数;对于关键字参数需要使用**
    lambda 参数列表:语句
    map(函数,序列,[seq]...)
    filter(函数,序列)
    list comprehension
    reduce(函数,序列)
    apply(函数,[元组参数[,词典参数]])        由于*和**,已经过时
    要将类的方法或者属性设置为private,则名字以__开头;在内部,这种名字被翻译成_class-name__name,那么通过class/object._class-name__name还是可以访问
    以_开头的名字不会通过from module import *被import
    可以通过class的__base__属性获取其baseclass
    对于多继承,若是一个方法由多个超类实现,则最终使用的是声明靠前的父类的方法
    callable()
    getattr(object, name[, default])
    hasattr(object, name)
    setattr(object, name, value)
    isinstance(object, class)
    issubclass(A, B)
    python使用异常对象来描述异常,若是异常不被处理,则程序终止并打印trackback
    raise SomeClass[, 'str']    自动创建一个instance
    raise someObject
    import exceptions    dir(exceptions)
7 / 24 / 2008
    常用异常
       Exception
       AttributeError
       IOError
       IndexError
       KeyError
       NameError
       SyntaxError
       TypeError
       ValueError
       ZeroDivisionError
    __metaclass__ = type
    __init__       构造函数
    __del__        析构函数(尽量不使用)
    重载构造函数,需要显示调用super的构造函数,否则对象初始化不完整
    def __init__(self[,...]):
        BaseClass.__init__(self[,...])
    def __init__(self[,...]):
       super(CurrentClass, self).__init__([...])
    __len__(self):
    __getitem__(self, key):
    __setitem__(self, key, value):
    __delitem__(self, key):
    staticmethod(smeth)    smeth不需要参数self
    classmethod(cmeth)    cmeth需要参数cls
    @staticmethod
    @classmethod
    property    __getattribute__(self, name)    __getattr__(self, name)    __setattr__(self, name, value)    __delattr__(self, name)
    def __iter__(self):
    yield    generator是一个包含关键字yield的函数
    if __name__ == '__main__':
    sys.path
    PYTHONPATH
    package中必须有一个模块__init__.py
    module.__all__定义模块的公共接口,from module import *只能获取__all__中的属性
    module.__file__        模块的存放路径
    import webbrowser
    import fileinput
    import sets
    import heapq
    import collections
    import time
    import shelve
    import re
    变量在第一次赋值时创建;变量没有类型,只是简单地指向有类型的对象
    变量是系统表中的表项,每个表项还有用于连接对象的空间;对象是一块分配的内存,存放了值;引用是变量对对象的指针
    对象的结构比较复杂,需要记录对象的类型以及引用计数等
    变量没有类型,对象才有类型,变量只是一个名字与引用的组合;变量在特定时间引用了特定的对象
    一个变量可以指向任意类型的对象
    对象的引用计数支持了自动回收机制
    复制一个list的最常用的方式是nl = l[:]
    Python会缓存小的integer和小的string,而大多数对象在不用时立即回收
    import sys
    sys.getrefcount()
    在Python中,零字节\0(null)不能终止一个字符串,实际上,python中没有字符串终止字符。字符串文本和长度都存放在内存中
    若是python不能识别\后面的转义序列,则将\作为字符保存在字符串中\\
    Python中的字符串不需要提前分配空间,而C中需要
    Python中不能通过+来混合数字和字符串
    格式化输出时,若有多个输出值,要将其组成tuple
    任意类型对象都可以转化为string,任意类型对象都可以使用%s格式化输出
    对于基于模式的文本处理,要使用re模块
    建议使用string类的方法,而不是string模块,string模块deprecated
    每一个Python模块有一个内置变量__name__,若是模块作为程序运行则该变量被设置为__main__,若是import则不会。该特点有利于编写可重用的代码,可以将代码组织为函数,既能import也能执行
    list可以看作是对象引用的数组,类似于C中的指针数组
    因为list存放的是对象引用,所以在改动list时会影响对象的引用计数
    list.append() + list.pop() ---> stack
    dictionary可以看作是对象引用的hash表
    dictionary是无序的,所以不能直接使用for,可以通过d.keys()控制遍历
    tuple类似于list,但是immutable
    变量存放的是对象的引用,通过变量修改对象可能会影响到对象的其他引用
    COPY: l[:]   d.copy()   只是最上层的复制
                import copy    copy.deepcopy()   全面复制
    任何immutable对象都可以成为词典的key
    tuple、list、dictionary中存放的都是对象的引用
7 / 25 / 2008
    with/as     from __future__ import with_statement
    对于单个block,所有语句的缩进必须相同,否则就是语法错误
    ()、[]、{}中的语句可以占据多行,语句不会终止除非遇到闭包对
    隐式赋值:import、from、def、class、for、function arguments
    tuple/list unpacking assignments
    sequence assignments
    tuple assignment是交换变量值的好方式
    sequence assignment有着很复杂的使用方式,但是code非常漂亮
    +=进行原地改动,而不是像+创建一个新的对象,所以效率要好一些;注意共享引用的影响
    import操作后模块名就成为了调用者的变量
    from module import *不会获取以单下滑线开头的变量_X
    __X__类型的变量有特殊含义
    __X类型的变量是局部与闭包的class的
    单下滑线_记录了交互工作时最后一个表达式的结果
    print >> fileobj, ...
    iterator    StopIteration
    iterator = iter(obj)
    iterator.next()
    __iter__    __getitem__
    range
    zip/map
    zip(key, value)
    for (k, v) in zip(keys, values): d[k] = v
    dict(zip(keys, values))
    for (offset, item) in enumerate(sequence)
    generatorobj = enumerate(s)
    generatorobj.next()
    list comprehension可以有多个for loop,其类似于与普通的嵌套for,但是运行更快
    docstring要出现在描述的module、function或者class的可执行语句之前,python会自动识别这些描述,将它们写入对应对象的__doc__属性
    def是可执行语句,直到运行到def函数才被创建。def可以与其他可嵌套结构进行嵌套
    def创建一个函数对象,并给其赋名。由于函数也是对象,而变量没有类型,所以可以有多个函数名对应一个函数
    参数传递传递的对象引用,所以在改变参数时要注意不要影响调用者
    Python中的一切都是runtime的,所以函数对象的创建也是动态的
    def在运行时才创建函数,因为def是一个语句,所以可以出现在语句可以出现的任何地方,例如if结构
    由于变量是动态创建的,所以python在运行时根据对其赋值的位置将其绑定到特定的namespace,从而确定其可见范围
    在一个函数中定义的变量其namespace位于该函数内,可以与函数外部的变量同名而不发生冲突
    在函数外定义的变量在整个文件范围内有效,为global的
    一个模块构成了一个全局范围,global变量是模块对象的attribute,可以在模块内作为变量使用
global变量的可见范围为单个模块,若要使用某个模块的global变量,必须进行import操作。当提到global,想到module
    函数内部的变量缺省为局部变量,也可以通过res指定。注意变量不是对象
    因为函数可以递归调用,所以实际上是一次函数调用创建一个新的局部范围,而不是函数定义创建一个局部范围
    任何在函数内部赋值而定义的变量都是局部的:语句、import、def、参数传递等等
    变量的可见范围由它被赋值(被创建)的地方决定
    交互方式时的所有代码属于模块__main__,所以交互时创建的变量也是存在于模块中
   
    名字解析最多有4个范围:local、函数、global和built-in
    由于变量是动态创建的,而且局部变量可以与全局变量同名,所以在一个函数中创建或者改变的变量除非声明为global,否则当作局部变量来处理,不同于同名全局变量
    若是仅仅是使用的话可以直接引用外部变量
    attribute名字的解析处理方式不同于variable名字
    python的简单类型对象是immutalbe的,变量赋值会导致新的对应对象的创建和引用传递
    python有垃圾回收功能
    python的long只受内存限制,float为双精度,int范围依赖于平台
    简单类型也有自己的构造函数
    python中所有的数据值都有对应的对象,所以变量赋值实质上是对后台对象引用的转换,对于简单类型对象本身没有变化,变量在特定时间只能指向一个对象,可以通过id函数检测变量引用的对象标识
    在Python中,简单数据类型并不是原始数据类型,而是完善的对象,它们有自已的方法和类。另外,这些简单的内置类型是不可改变的,这意味着:创建对象之后,您无法更改对象的值。如果需要新值,则必须创建新的对象
    python不存在内置字符数据类型
    bool, int, long, float, complex            immutable
    tuple  ---  immutable  ---  tuple是一个异构容器
    str      ---  immutable
    LEGB
    尽量不要改动全局变量,在当前模块以及其他模块
    工厂函数 factory function
    在不使用类的情况下,global变量、工厂函数、缺省参数是函数记住状态信息的主要方式

    lambda引入了新的local范围
    lambda是表达式
    函数或者lambda是动态创建的,它们被调用时才会创建,才会解析变量(按LEGB搜索)
    def makeActions():
        acts = []
        for i in range(5):
             acts.append(lambda x, i=i: i**x)
        return acts