《Python 基础教程》笔记

第1章

幂运算符:**,不是^
长整数:在整数结尾加上L,如:100000000000000000000L

Python 3中,print 从语句变成了函数,print 42 要写成 print (42)

在UNIX系统下,在脚本开头加上 #!/usr/bin/env python 可以让脚本像普通程序一样执行,不需要显式地使用Python解释器

Python 3.0 已不再使用反引号,应该使用 repr() 函数

inputraw_inputinput 需要用户输入合法的 Python 表达式。Python 3.0 中,raw_input 被重新命名为 input

原始字符串 r’c:\windows’(类似 Objective-C 中的 @“"?)
原始字符串的最后一位不能是''
原始字符串在写正则表达式的时候很有用

Unicode 字符串 u’hello, world'

第2章 列表和元组

两种主要的容器:序列和映射。序列一共有六种,包括列表和元组(不可变列表),还有字符串、Unicode字符串、buffer对象、xrange对象。

注意:负数索引

通用序列操作:索引、分片(slicing)、加、乘;计算长度、最大最小值;迭代。

slicing 的应用:复制表

>>> x = [1, 2, 3]
>>> y = x[:]

检查成员资格(某元素是否在容器中):in 运算符。

list,将字符串转换为列表

>>> list(‘hello’)
[ ‘h’, ‘e’, ‘l’, ‘l’, ‘o’ ]

分片赋值。可插入与原分片不等长的列表。可以利用分片赋值实现删除元素。

列表方法:append, count, extend, index, insert, pop, remove, reverse, sort

tuple 函数(其实不是函数,是类)可以将序列转换为元组

关于元组,这句话很精辟:

除了创建元组和访问元素之外,也没有太多其他操作。

元组的作用:元组可以在映射中当作键使用(?);很多内建函数和方法的返回值是元组。

第3章 字符串

格式化字符串时,如果字符串本身包括 ‘%',需要使用’%%'的形式。

字符串格式化(这部分写得很全面)

字符串方法:find, join, lower, replace, split, strip, translate

第4章 字典

字典是 Python 唯一的内建映射类型。

dict 函数,从列表或其他映射建立字典

?什么是关键字参数。例如:从关键字参数建立字典 d = dict(name='michael', age=42)

使用字典格式化字符串,%后面使用括号,表示这里是一个字典的 key

字典方法: clear, copy, fromkeys, get, has_key, items, iteritems, values, itervalues, keys, iterkeys, pop, popitem, setdefault, update,

注意,popitem 实际上是 随机 弹出一个值,因为字典不保存 items 的顺序(在 JavaScript、JSON 中也是这样)。

第5章 条件、循环和其他语句

赋值语句

交换两个变量的值:x, y = y, x。这里用到的特性叫做“序列解包(sequence unpacking)”。处理返回元组的函数,序列解包特性十分有用:key, value = dict.popitem()。。

Python 3.0 之前,不兼容类型比较(例如比较一个整形数和一个字符串)不会导致语法错误,但是结果是不可预期的。Python 3.0 起,不再允许比较不兼容类型。

短路逻辑(惰性求值)示例:name = raw_input('input name...') or 'unknown'

只要能使用 for 循环,就不要用 while 循环。

zip() 函数可以将两个序列压缩到一起。

使用 for item in list: 处理列表时,如果需要得到 index,可以使用 enumerate() 函数:for index, item in enumerate(list):

在循环中使用 else 子句,表示循环没有被 break 语句打断而跳出。

from math import sqrt
for n in range(99, 81, -1):
	root = sqrt(n)
	if root == int(root)
	print n
	break
else:
	print "didn't find it!"
	

列表推导:用其他列表创建新列表。可以结合条件判断语句:

[x*x for x in range(10) if x % 3 == 0]

命令空间类似于不可见的字典。

第6章 抽象

文档字符串

def square(x):
	'计算x的2次方'
	return x ** 2;

函数的位置参数与关键字参数。关键字参数结合默认值使用,非常方便。

收集参数(不确定参数个数),将其后的所有参数收集到一个元组中。
关键字参数需要使用 **,将关键字参数整理到一个字典(不是元组)中。

作用域可以理解为一个不可见的字典。

嵌套作用域与闭包。

第7章 更加抽象

面向对象 三原则

  • 封装
  • 继承
  • 多态

封装和多态有些类似,但出发点不同。封装侧重于调用者不必知道方法的具体实现,多态侧重于要使用某个方法时不必去管对象具体属于哪个类型。

这里使用 isinstance 进行类型检查是为了说明一点,类型检查一般来说不是什么好方法,能不用则不用。

因为 isinstance 进行类型检查破坏了代码的多态性。

除非是遗留代码,不然应当使用新式类,在模块或脚本开头使用赋值语句:__metaclass__ = type

Python 并不直接支持私有属性或方法,要表明某个方法是私有方法时,可以在前面加上两个下划线。import 语句会自动忽略前面带有下划线的属性和方法。

尽量避免使用多重继承。

Python 不支持接口,但在调用方法之前可以确定是否存在该方法。

第8章 异常

Python 使用异常对象来表示异常情况。异常对象未被处理或捕捉时,采用回溯(traceback)来终止执行。

raise 语句

异常的捕捉与“上浮(propagate ouf of the functions where the're called)”。如果在发生异常时未提供except语句,异常会上浮(bubble up)到调用该函数的函数中,一直到程序的最顶层。

查看 Python 内建的异常类型:

import exceptions
print dir(exceptions)

捕捉到了异常但是暂时不想处理,可以调用不带参数的 raise 对异常进行“转发”:

try:
	// some code
except:
	// 
	raise

一个 try 语句之后可以跟随多个 except 语句,用于捕捉不同类型的异常。

except 语句之后可以将多种类型的异常通过元组的方式列出:
except: (ZeroDivisionError, TypeError, NameError)

在异常处理代码中使用异常对象:

try:
	// ...
except: (ZeroDivisionError, TypeError), e:
	print e

Python 3.0 中的写法是 except: (ZeroDivisionError, TypeError) as e

try/except 语句可以加上else子句:

try:
	// ...
except:
	// ...
else:
	// ...

这里的 else 只有在没有发生异常的情况下才会被调用。

finally 子句,用于在有异常发生的情况下的清理工作。finally 子句一般用于关闭文件、套接字连接、数据库连接等。

一般来说,使用 try/except 比使用 if/else 更 pythonic!
请求宽恕易于请求许可。

在 Objective-C 中正好相反吗?

第9章 魔法方法、属性和迭代器

这章讲得不是很细。要重读英文版

魔法方法:名字前后带下划线的、具有特殊作用的方法。

用得最多的魔法方法:__init__

调用父类构造方法的两种形式

  • Unbound Superclass Constructor (那么 Python 所有的方法都可以当作静态方法来调用?)
class SongBird(Bird):
	def __init__(self):
		Bird.__init__(self)
		// ...
  • 使用 super 函数
__metaclass__ = type // super 方法只对新式类有效
class SongBird(Bird):
	def __init__(self):
		suepr(SongBird, self).__init__()
		// ...

注意:Python 3.0 中 调用 super 函数不再需要提供参数。

应该尽量使用新式类。

Python 中的 protocol

序列和映射成员访问规则:__len__(self), __getitem__(self.key), __setitem__(self.key, value), __delitem__(self.key)

property 函数:用于对 get/set 函数进行组织,最多接受4个参数:
property (fget, fset,fdel, doc)

静态方法与类成员方法

静态方法不需要self作为参数,类方法需要提供一个叫做 cls 参数。

正式的说法是,一个实现了 __iter__ 方法的对象是可迭代的,一个实现了 next 方法的对象是迭代器。

生成成器:包括 yield 语句的函数

生成器推导式(?)

生成器是由两部分组成的:生成器的函数和生成器的迭代器。

Generators are ideal for complex recursive algorithms that gradually build a result.

八皇后问题的例子:要多看几遍才能懂。bitbucket repo

第10章 自带电池

作为“主程序”或作为模块导入其他程序时,变量 __name__ 的值是不一样的。可根据 __name__ 来确定是否需要执行代码:

if __name__ == '__main__': test()

模块的文件名要和模块名称一致。

包就是一个目录,为了表明该目录是一个包,需要在其中创建一个名为 __init__.py 的文件(模块)。

导入模块的三种方式:

  • import drawing:只有 __init__ 模块中的内容可用。
  • import drawing.colors:只能通过全名 drawing.colors使用
  • from drawing import colors:可以通过短名称 colors 使用

使用列表推导式查看一个模块里的内容:

import copy
[n for n in dir(copy) if not n.startswith('_')]

使用 __all__ 变量,可以列出模块的所有“公有接口(public interface)”,也就是使用 import * 时导入的所有方法。如果模块中没有定义 __all__ 变量,那么 import * 会导入其中的所有方法。

import copy
print copy.__all__

查看包的源代码文件路径

import os
print os.__file__

标准库中的实用资源

sysargvpath

osenvironseqpathseplinesep

fileinput

高级数据结构

集合(Set)、堆(heapq,heap queue)、双端队列(deque, double-end queue)

time 模块

random 模块

shelve 文件存储模块

re 模块:escape() 函数