Python核心编程笔记1 基础知识
Contents
这本书翻译稀烂, 然而我还是忍着看完了第一部分
Python基础
基本风格指南
- 跨行代码可以使用反斜杠
\
- 变量赋值通过引用传递
- python不支持
++
,--
, 请使用+=
和-=
- 多元赋值: 实际上是元组赋值:
a, b = 1, 2
等价于(a, b) = (1, 2)
. 在python中, 没有括号的分组默认是元组, 而不是列表 - 下划线标识符:
_xxx
: 此类属性不会被from module import *
导入. 另外python不提倡使用此语句导入包, 容易造成名空间混乱__xxx__
: 类的特殊方法_xxx
: 类的私有变量名, 在子类中建议使用, 可以避免和父类冲突
__name__
: 如果module被导入, 变量值为module名, 如果被执行, 为__main__
内存管理
python的垃圾收集器实际上是引用计数器+循环辣鸡收集器
Python对象
Built-in 类型
- 内建类型略
- 切片对象的复制问题
- 对象值的比较可以用
id()
, 类似于c中的取地址操作&
,a is b
可以比较a与b的地址 - python不支持函数或者方法重载
- 类型工厂函数/内建函数: 看上去是函数, 实际上是生成了该类型的一个实例:
int
,float
,complex
,str
,list
,turple
,dict
,type
,bool
,set
,super
等
- 可变类型: 列表和字典. 不可变类型: 数字, 字符串, 元组
数字
- 数字的隐式类型转换和c++相似
- 几个取整的常用工厂函数:
round(3.141, 2) = 3.15
: 按四舍五入取整int(3.14) = 3
: 直接截取整数部分, 返回intfloor(-0.2) = -1.0
: 取最接近但小于原数的整数, 返回float
序列
字符串
- 切片索引的一个小技巧: 用
None
作为索引值, 可以使用一个变量作为索引从第一个遍历到最后一个, 即s[:None] = s
|
|
- 字符串比较是按ASCII值比较的, 因此大写字母一定比小写字母小. 即
cmp('Z', 'a' ) == -1
string
库的常用方法和属性:
- 替换
'abcde'.replace('abc', 'xyz') = 'xyzde'
- 分割
'a/bxxx/c'.split('/') = ['a', 'bxxx', 'c']
- 删除头尾空格
' abc '.strip() = 'abc'
列表
- 删除元素时, 知道元素值用
del(element)
, 不知道元素只知道序号用remove(index)
- 列表的
sort()
和reversed()
都是inplace操作, 返回None, 而sorted()
和reversed()
是工厂函数, 可以作为值返回
元组
- 单元素元组的坑: 只有一个元素的元组需要加逗号, 否则容易和工厂函数混淆:
|
|
- 所有多对象, 用逗号分隔的, 没有明确符号定义的集合默认为元组
浅拷贝, 深拷贝和可变/不可变对象的例子
|
|
- hubby, wifey这两个对象是新的, 但他们的内容不一定
- 序列类型对象的默认拷贝是浅拷贝, 可以通过切片, 工厂函数, **
copy()
**实现 - 不可变对象(例子中是字符串)的拷贝, 实际上是删除变量引用, 创建新的对象, 然后转移引用到新变量
- 可变对象(例子中是列表)的拷贝只是复制了引用
- 想要深拷贝请使用
copy.deepcopy()
- 对原子元素组成的元组进行深拷贝无效
映像和集合类型
字典
- 只需要字典名就可以遍历字典key, 但key是无序的
- 检查key是否存在使用
in
和not in
,has_key()
即将被弃用 - key必须是可hash的, 也就是不可变对象. 可以使用
hash()
检验 - 字典的常用方法有
iteritems()
返回一个迭代器, 而不是数组values()
返回一个包含字典所有值的列表
集合
无序, 只能用工厂函数构造
条件和循环
循环语句
- 三元组表达式:
A if EXP else B
, 等价于exp? A:B
else
可以放在循环之后, 只要循环是正常结束的, 会执行else
中的语句
迭代器
- 定义: Iterator类是实现了
__iter__()
和next()
的类.例子出处
|
|
在for
循环中迭代该类, 会依次调用迭代器的next()
方法, 直到StopIteration
抛出, for
循环会捕捉处理.
2. 将其他序列转化成迭代器可以直接使用iter()
工厂函数. 如果传递两个参数给iter()
, 他会重复调用func
, 直到迭代器的下个值等于sentinel
列表解析式
只说一点, 列表解析式可以套双层循环:
|
|
scala也有类似的语法, 也许是从函数式语言中引进的
生成器表达式
和生成器类似, 有关生成器的内容见后文, 这里只给出和列表解析式的区别:
|
|
可见只是将方括号换成了圆括号. 对生成器表达式迭代会引发和生成器类似的效果, 即延迟计算(lazy evaluation), 也可以理解为懒惰的列表解析, 是对内存更友好的结构.
文件和输入输出
内建函数open()和file()
常见访问模式
r
: 只读w
: 写入,若文件存在则首先清空a
: 写入, 若文件存在则追加w+
/a+
: 读写模式,参考前两个模式
内建方法
readline()
: 读取打开文件的第一行, 不会删除行结束符readlines()
: 读取所有行并把他们作为一个字符串列表返回write()
: 写入, 但不会自动加入换行符writelines()
: 将列表写入, 但不会自动加入换行符- 文件对象可以直接作为文件迭代器:
|
|
错误和异常
有些行为, 比如用户退出或者系统退出并不应该被捕获, 需要提前处理:
|
|
2.5版本之后, KeyboardInterrupt和SystemExit被从Exception里移出和Exception平级, 因此不必单独处理这两种情况:
|
|
最后, Exception的父类是BaseException
上下文管理
|
|
断言
一个用try语句捕捉断言产生的错误的例子:
|
|