深入Python学习

深入 Python 3 中文版
——摘录

1、Python 里面没有子程序。所有的东西都是一个函数,所有的函数都返回一个值(即使它是 None 值),并且所有的函数都以 def 开头。

2、只要你有一个命名参数,它右边的所有参数也都需要是命名参数。(确认一下,如果是多个参数的时候,第一个不用命名参数,而从第二个开始用命名参数是否可以。

3、一个 docstring (文档字符串),如果有的话,必须是一个函数里面定义的第一个东西(也就是说,紧跟着函数声明的下一行)。

4、很多 Python 的集成开发环境(IDE)使用 docstring (文档字符串)来提供上下文敏感的文档,以便于当你输入一个函数名称的时候,它的 docstring 会以一个提示文本的方式显式出来。

5、通过添加一个目录名称到 sys.path 里,你可以在运行时添加一个新的目录到 Python 的搜索路径中,然后无论任何时候你想导入一个模块,Python 都会同样的去查找那个目录。只要 Python 在运行,都会一直有效。通过使用 sys.path.insert(0, new_path),你可以插入一个新的目录到 sys.path 列表的第一项,从而使其出现在 Python 搜索路径的开头。这几乎总是你想要的。万一出现名字冲突(例如,Python 自带了版本 2 的一个特定的库,但是你想使用版本 3),这个方法就能确保你的模块能够被发现和使用,替代 Python 自带的版本。

6、Python 使用 try...except 块来处理异常,使用 raise 语句来抛出异常。 Java 和 C++ 使用 try...catch 块来处理异常,使用 throw 语句来抛出异常。Python 里面所有的名称都是区分大小写的:变量名、函数名、类名、模块名称、异常名称。像 C 语言一样, Python 使用 == 来做比较,用 = 来赋值。深入Python 3 P57

7、模块是对象,并且所有模块都有一个内置的属性 __name__。一个模块的 __name__ 属性取决于你怎么来使用这个模块。如果你 import 这个模块,那么 __name__ 就是这个模块的文件名,不包含目录的路径或者文件的扩展名。但是你也可以当作一个独立的程序直接运行这个模块,那样的话 __name__ 将是一个特殊的默认值 __main__。(深入Python 3 P62)

8、常见的数值运算
        Python 2 对于int[整型] 和 long[长整型] 采用不同的数据类型。int 数据类型受到 sys.maxint 的限制,因平台该限制也会有所不同,但通常是 232‐1 。Python 3 只有一种整数类型,其行为方式很有点像 Python 2 的旧 long[长整数] 类型。
        在 Python 2 中,运算符 / 通常表示整数除法,但是可以通过在代码中加入特殊指令,使其看起来像浮点除法。在 Python 3 中,/ 运算符总是表示浮点除法。(深入Python 3 P70)
        在布尔类型上下文环境中,非零整数为真;零为假。非零浮点数为真; 0.0 为假。请千万小心这一点!如果有轻微的四舍五入偏差(正如在前面小节中看到的那样,这并非不可能的事情),那么 Python 将测试 0.0000000000001 而不是 0 ,并将返回一个 True 值。分数也可在布尔类型上下文环境中使用。无论 n 为何值,Fraction(0, n) 为假。所有其它分数为真。(深入Python 3 P73)

9、列表
      任何非空列表的最后一个元素总是 a_list[‐1] 。如果负数令你混淆,可将其视为如下方式: a_list[‐n] == a_list[len(a_list) ‐ n] 。因此在此列表中, a_list[‐3] == a_list[5 ‐ 3] == a_list[2]。(深入Python 3 P75)
     a_list[:] 是对列表进行复制的一条捷径。
      append() 方法向列表的尾部添加一个新的元素(可以是列表,列表整体作为一个新的列表项)。
      insert() 方法将单个元素插入到列表中。第一个参数是列表中将被顶离原位的第一个元素的位置索引。
      extend() 方法只接受一个列表作为参数,并将该参数的每个元素都添加到原有的列表中。(深入Python 3 P79)
      in 运算符将会比使用 count() 方法要略快一些。
      如果在列表中没有找到该值,index() 方法将会引发一个例外。如果试图删除列表中不存在的元素,它将引发一个例外。对空列表调用 pop() 将会引发一个例外。
      
pop() 列表方法将删除列表中最后的元素,并返回所删除的值。传给 pop() 方法一个位置索引值。它将删除该元素(深入Python 3 P83)

10、元组
        元素 是不可变的列表。一旦创建之后,用任何方法都不可以修改元素。
        元组的速度比列表更快。
       
 一些元组可用作字典键,列表就不可以,因为列表不是不可变的。
        tuple() 函数接受一个列表参数返回一个元组,list() 函数接受一个元组参数并返回一个列表。即, tuple() 冻结列表,而 list() 融化元组。
        为创建单元素元组,需要在值之后加上一个逗号。没有逗号,Python 会假定这只是一对额外的圆括号,虽然没有害处,但并不创建元组。
        可使用元组来一次赋多值。

11、集合(深入Python 3 P90)
  集合set 是可以包含任何数据类型的值的无序“袋子”。
  要创建空集合,可不带参数调用 set() 。由于从 Python 2 沿袭而来历史的古怪规定,不能使用两个花括号来创建空集合。该操作实际创建一个空字典,而不是一个空集合。
  集合形如:a_set = {1, 2},列表转化为集合:a_set = set(a_list)
  add() 方法接受单个可以是任何数据类型的参数,添加一个集合中已有的值,不会引发一个错误;只是一条空操作。
  update() 方法可以接受一个多个集合/列表作为参数,会把列表中所有的元素添加到初始集合中。
  discard() ,remove()均接受一个单值作为参数,然后删除该参数,区别在这里:如果该值不在集合中,remove() 方法引发一个 KeyError 例外。而discard不会,只是一条空操作。
  pop() 方法从集合中删除某个值,并返回该值。
  union() 方法返回一个新集合,其中装着 在两个 集合中出现的元素。
  intersection() 方法返回一个新集合,其中装着 同时 在两个集合中出现的所有元素。
  difference() 方法返回的新集合中,装着所有在 a_set 出现但未在 b_set 中的元素。
  symmetric_difference() 方法返回一个新集合,其中装着所有 只在其中一个 集合中出现的元素。
  所有 a_set 的成员均为 b_set 的成员,a_set为b_set的子集;反过来,b_set 是 a_set 的 超集,因为 a_set 的所有成员均为 b_set 的成员。

12、字典
  字典 是键值对的无序集合。Python 的字典为通过键获取值进行了优化。
  在字典中不允许有重复的键。对现有的键赋值将会覆盖旧值。字典键是区分大小写的。(深入Python 3 P103)
  二维列表可以通过dict转化为字典:listTest = [['password', 'PapayaWhip']],转化:dict(listTest),结果:{'password': 'PapayaWhip'}

13、布尔上下文环境中的字典
  无论列表,无组,集合,还是字典,只要其元素为空,都为假(即if判断为假),否则为真(即if判断为真)

14、NONE(深入Python 3 P105)
        None 是唯一的空值。它有着自己的数据类型(NoneType)。
处理文件和目录
处理文件名和目录名
        split 函数分割一个完整路径并返回目录和文件名。os.path.splitext() 函数,它分割一个文件名并返回短文件名和扩展名。(深入Python 3 P114)
罗列目录内容
        glob 模块接受一个通配符并返回所有匹配的文件和目录的路径。在glob模式中你可以使用多个通配符。glob.glob() 函数返回一个相对路径的列表。当你希望构造一个从根目录开始或者是包含盘符的绝对路径时,你就需要用到os.path.realpath()函数了。
获取文件元信息
        调用os.stat() 函数返回一个包含多种文件元信息的对象。
15、列表解析
(深入Python 3 P117)
16、字典解析
(深入Python 3 P120)
17、其他同字典解析有关的小技巧
交换字典的键和值。
        a_dict = {'a': 1, 'b': 2, 'c': 3}
        {value:key for key, value in a_dict.items()}
        {1: 'a', 2: 'b', 3: 'c'}
18、集合解析
(深入Python 3 P124)

19、字符串
Unicode入门。
(深入Python 3 P129)
格式化字符串(深入Python 3 P136)
复合字段名(深入Python 3 P141)
        '1000{0[0]} = 1{0[1]}'.format(si_suffixes),结果:1000KB = 1MB
        si_suffixes是一个列表。所以{0[0]}指代si_suffixes的第一个元素,即'KB'。同时,{0[1]}指代该列表的第二个元素,即:'MB'。
        使用列表作为参数,并且通过下标索引来访问其元素(跟上一例类似)
        使用字典作为参数,并且通过键来访问其值
        使用模块作为参数,并且通过名字来访问其变量及函数
        使用类的实例作为参数,并且通过名字来访问其方法和属性
        以上方法的任意组合使用列表作为参数
       例子:'1MB = 1000{0.modules[humansize].SUFFIXES[1000][0]}'.format(sys)
格式说明符
其他常用字符串方法(深入Python 3 P144)
       如果中文的字符串,使用splitlines()方法获取列表后,我直接打印列表,输出的不是中文,但是用for一个个输出的时候,是中文???(深入Python 3 P146)//TODO
字符串的分片(深入Python 3 P148)
       字符串的分片就是截取其中的任意部分形成新串,和列表的分片是一样的处理。a_string[3:11],如果省略了第一个索引值,Python会默认它的值为0,同样省略后面的,为默认取到结尾。就像给列表做分片一样。
STRING VS. BYTES(深入Python 3 P150)
       一个不可变(immutable)的Unicode编码的字符序列叫做string。一串由0到255之间的数字组成的序列叫做bytes对象。
       使用“byte字面值”语法b''来定义bytes对象,如:by = b'abcd\x65'
       例子说by = b'abcd\x65' by += b'\xff'输出结果为b'abcde\xff',可是我的试验结果为:abcde�,是乱码啊,怎解???//TODO
       bytes对象是不可变的,不可以给单个字节赋上新值,如果需要改变某个字节,可以组合使用字符串的切片和连接操作(效果跟字符串是一样的),或者也可以将bytes对象转换为bytearray对象。可以使用下标标记给bytearray对象的某个字节赋值。并且,这个值必须是0–255之间的一个整数。                 >>> by = b'abcd\x65'
       >>> barr = bytearray(by) ①
       >>> barr[0] = 102 ③
       >>> barr
       bytearray(b'fbcde')
       bytes对象有一个decode()方法,它使用某种字符编码作为参数,然后依照这种编码方式将bytes对象转换为字符串,对应地,字符串有一个encode()方法,它也使用某种字符编码作为参数,然后依照它将串转换为bytes对象。可以类比Java中String和Byte的转换。(深入Python 3 P154)
补充内容:PYTHON码的编码方式
       Python 3会假定我们的源码 — 即.py文件 — 使用的是UTF‐8编码方式。Python 2里,.py文件默认的编码方式为ASCII。

正则表达式(深入Python 3 P160)
案例研究: 街道地址(深入Python 3 P161)
———————————————————华丽的分隔线————————————————
今天2014.02.12距上次更新2014-01-13一个月有余,都没有更新python学习,真是养成习惯难,荒废却如此简单。你学习,也是过一天,不学习,也一样过一天,但就是这一天天,形成了人与人之间的差别,等到三五年过后感叹之时,还能再有几个三五年呢?
—————————————————————华丽的分隔线
————————————————
       同其它语言一样,^ 匹配字符串开始. $ 匹配字符串结尾。(深入Python 3 P162)
       s = '100 BROAD' re.sub('ROAD$', 'RD.', s) 结果:'100 BRD.'//TODO这似乎还没怎么介绍,只是使用了一下。
      为了在正则表达式中表达这个独立的词,你可以使用‘\b’。它的意思是“在右边必须有一个分隔符”(深入Python 3 P163)
      为了解决‘\’字符传染的问题,可以使用原始字符串。这只需要在字符串的前面添加一个字符‘r’。它告诉python,字符串中没有任何字符需要转义。‘\t’是一个制表符,但r‘\t’只是一个字符‘\’紧跟着一个字符t。我建议在处理正则表达式的时候总是使用原始字符串。
       re模块最基本的方法是search()函数。它使用正则表达式来匹配字符串(M)。如果成功匹配,search()返回一个匹配对象。匹配对象中有很多的方法来描述这个匹配结果信息。如果没有匹配到,search()返回None。你只需要关注search()函数的返回值就可以知道是否匹配成功。
      re.search('^M?M?M?$', 'M'),?表示匹配是可选的,使用语法{N,M}可以更方便表示可选,{1,4} 匹配1到4个前面的模式,(A|B) 匹配A模式或者B模式中的一个(深入Python 3 P168)
松散正则表达式(深入Python 3 P174)      
      松散正字表达式和普通紧凑的正则表达式有两点不同: 空白符被忽略。注释信息被忽略。    
      注意,如果要使用松散正则表达式,需要传递一个叫re.VERBOSE的参数。re.search('^M?M?M?$', 'M', re.VERBOSE)。ython不会自动检测一个正则表达式是否是松散正则表达式,而需要明确的指定。
案例研究: 解析电话号码(深入Python 3 P176)  
      如果search()方法匹配不成功,也就是返回None,这就不是返回的一个正则表达式匹配对象。它没有groups()方法,所以调用None.groups()将会抛出一个异常。对search()函数的返回值调用groups()方法。它会返回一个这个正则表达式中定义的所有分组结果组成的元组。
      phonePattern = re.compile(r'(\d{3})\D*(\d{3})\D*(\d{4})\D*(\d*)$')
      phonePattern.search('work 1‐(800) 555.1212 #1234').groups()
      结果:('800', '555', '1212', '1234')(深入Python 3 P182页最终的表达式)  
闭合 与 生成器(深入Python 3 P187)  
设计一个 Python 类库用来自动进行英语名词的复数形式转换。
      在动态函数中使用外部参数值的技术称为 闭合【closures】。
      (深入Python 3 P217)
      class LazyRules:
            rules_filename = 'plural6‐rules.txt'
      r1 = LazyRules()
      r2 = LazyRules()
      r2.rules_filename = 'r2‐override.txt'
      r2.__class__.rules_filename = 'papayawhip.txt'
      print r1.rules_filename 结果:papayawhip.txt
      print r2.rules_filename 结果:plural6‐rules.txt

      已经覆盖(overridden)了该属性(如这里的 r2 )的所有实例 将不受影响。而如果没有覆盖的话,就会受影响,结果都会为papayawhip.txt(深入Python 3 P220~221)
      这里有提到def __next__(self):方法,事实上,在2.7.3版本的Python环境下,该方法根本无法运行,会提示错误TypeError: instance has no next() method。
      正确的写法是
def next(self):
      readlines()将文件读入列表,readline()一行一行的读取文件。
      这里还发现一个问题是
,readline()出来的数据带有换行符,如果你要是拿这个读出来的值与其它值比较,会意外的发现比较结果不对。可以利用strip(),lstrip(),rstrip()方法去掉。(深入Python 3 P224)
      这里有一些LazyRules 示例需要细想的地方: 模式文件被打开(在 __init__()中),并持续打开直到读取最后一个规则。 当Python退出或最后一个LazyRules 类的实例销毁,Python 会最终关闭文件,但是那仍然可能会是一个很长的时间。如果该类是一个“长时间运行”的Python进程的一部分,Python可能从不退出, LazyRules 对象就可能一直不会释放。
      这种情况有解决办法。 不要在 __init__() 中打开文件并让其在一行一行读取规则时一直打开,你可以打开文件,读取所有规则,并立即关闭文件。或你可以打开文件,读取一条规则,用tell() 方法保存文件位置,关闭文件,后面再次打开它,使用seek() 方法 继续从你离开的地方读取。 或者你不需担心这些就让文件打开,如同本示例所做。
      编程即是设计, 而设计牵扯到所有的权衡和限制。让一个文件一直打开太长时间可能是问题;让你代码太复杂也可能是问题。哪一个是更大的问题,依赖于你的开发团队,你的应用,和你的运行环境。(深入Python 3 P226)
高级迭代器
      import re
      print re.findall('[0‐9]+', '16 2‐by‐4s in rows of 8')
      print re.findall('[A‐Z]+', 'SEND + MORE == MONEY')
     这几个值与书中讲的结果不一样,估计是2.7和3的区别,还需要看一下是何情况
      print re.findall(' s.*? s', "The sixth sick sheikh's sixth sheep's sick.")
      re.findall()函数不会返回重叠的匹配。第一个匹配和第二个匹配是重叠的,所以第一个被返回了,第二个被跳过了。然后第三个和第四个重叠,所以第三个被返回了,第四个被跳过了。最后,第五个被返回了。三个匹配,不是五个。(深入Python 3 P231)
在序列中寻找不同的元素
      Sets 使得在序列中查找不同的元素变得很简单,因为Python 集合不允许重复
      a_list = ['The', 'sixth', 'sick', "sheik's", 'sixth', "sheep's", 'sick']
      set(a_list)
      {'sixth', 'The', "sheep's", 'sick', "sheik's"}
      a_string = 'EAST IS EAST' set(a_string) {'A', ' ', 'E', 'I', 'S', 'T'}
作出断言
      assert 2 + 2 == 5, "Only for very large values of 2"
      Traceback (most recent call last):File "<stdin>", line 1, in <module> AssertionError: Only for very large values of 2
      如果Python 表达式求值结果为 False, assert 语句会抛出一个 AssertionError.你可以提供一个人类可读的消息,AssertionError异常被抛出的时候它可以被用于打印输出。
生成器表达式
      unique_characters = {'E', 'D', 'M', 'O', 'N', 'S', 'R', 'Y'}
      gen = tuple(ord(c) for c in unique_characters)#调用 next(gen) 返回迭代器的下一个值。
      gen =
tuple(ord(c) for c in unique_characters)

      (69, 68, 77, 79, 78, 83, 82, 89)
      生成器表达式类似一个yield值的匿名函数。可以将生成器表达式传给tuple(), list(), 或者 set()来迭代所有的值并且返回元组,列表或者集合。
      使用生成器表达式取代列表解析可以同时节省CPU 和 内存(RAM)。如果你构造一个列表的目的仅仅是传递给别的函数,(比如 传递给tuple() 或者 set()), 用生成器表达式替代吧!(深入Python 3 P235)

计算排列… 懒惰的方法!(深入Python 3 P236)
      permutations() 函数接受一个序列(这里是3个数字组成的列表) 和一个表示你要的排列的元素的数目的数字。函数返回迭代器,你可以在for 循环或其他老地方使用它。
      import itertools
      perms = itertools.permutations([1, 2, 3], 2)
      next(perms)
      结果:(1, 2)—[1, 2, 3]取2个的第一个排列是(1, 2)。

      list(itertools.product('ABC', '123'))
      结果:[('A', '1'), ('A', '2'), ('A', '3'),('B', '1'), ('B', '2'), ('B', '3'),('C', '1'), ('C', '2'), ('C', '3')]
      itertools.product()函数返回包含两个序列的笛卡尔乘积的迭代器。
      list(itertools.combinations('ABC', 2)) 
      结果:[('A', 'B'), ('A', 'C'), ('B', 'C')]
      itertools.combinations()函数返回包含给定序列的给定长度的所有组合的迭代器。这和itertools.permutations()函数很类似,除了不包含因为只有顺序不同而重复的情况。

(深入Python 3 P236)
      names=['Alex', 'Anne', 'Chris', 'Dora', 'Ethan','John', 'Lizzie', 'Mike', 'Sarah', 'Wesley']
      names = sorted(names)(如果没有这句,groupby的结果是乱的,只有输入序列已经按分组函数排过序才能正常工作。)
      groups = itertools.groupby(names, len)
      list(groups)(耗尽迭代器)
      groups = itertools.groupby(names, len)迭代器没有“重置”按钮。你一旦耗尽了它,就没法重新开始,得调用itertools.groupby()来创建一个新的迭代器。
      for name_length, name_iter in groups: ③
          print('Names with {0:d} letters:'.format(name_length))
              for name in name_iter:
                  print(name)

一种新的操作字符串的方法(深入Python 3 P245)
      字符串翻译从一个转换表开始, 转换表就是一个将一个字符映射到另一个字符的字典。实际上,“字符” 是不正确的 — 转换表实际上是将一个 字节(byte)映射到另一个。一个字符串的translate()方法接收一个转换表,并用它来转换该字符串。换句话说,它将出现在转换表的键中的字节替换为该键对应的值。在这个例子里, 将MARK “翻译为” MORK.
      translation_table = {ord('A'): ord('O')}
      translation_table输出结果:{65: 79}
      'MARK'.translate(translation_table)结果:'MORK'

将任何字符串作为PYTHON表达式求值(深入Python 3 P247)
eval()——Python 通用求值工具
eval('1 + 1 == 2')结果:True|eval('"A" + "B"')结果:'AB'|x = 5 eval("x * 5")结果:25
subprocess 模块允许你执行任何shell命令并以字符串形式获得输出。(深入Python 3 P249)
import subprocess
eval("subprocess.getoutput('ls ~')")
存在全局函数__import__(),它接收字符串形式的模块名,导入模块,并返回模块的引用。和eval()的能力结合起来,你可以构造一个单独的表达式来删除你所有的文件:eval("__import__('subprocess').getoutput('rm /some/random/file')")

单元测试(深入Python 3 P254)
Python 自带一个单元测试框架,被恰当地命名为 unittest 模块。
编写一个失败的测试,然后进行编码直到该测试通过。首先,你应该用一个空方法作为存根,同时确认该测试失败。

测试本身是类一个方法,并且该方法以 test 开头命名。(深入Python 3 P270)
self.assertRaises(roman2.OutOfRangeError, roman2.to_roman, 4000)
to_roman() 方法作为参数传递;你没有调用被测方法,也不是把被测方法作为一个字符串名字传递进去。我是否在之前提到过 Python 中万物皆对象


——未完待续


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值