SS 源码阅读小记
分类:技术
阅读一下某源代码,学习一些 Python 的基本知识 = =
- 本地使用
python -m pydoc <关键字>
搜索帮助 - Python 命令行下使用
help('<关键字>')
搜索帮助 - 时间充裕或者没有本地版本可以到 http://docs.python.org 搜索
- 还有疑问就只有去 http://stackoverflow.com 解决了……
注意:以下内容均为 Python 基础知识笔记,几乎都可以通过上述途径获得。
肉馅
使用 hashlib
模组求哈希值,需要首先指定算法来创建 hash object,而后使用。
该模组提供了 new
函数,通过填入算法名得到 hash object,例如 hashlib.new('sha1')
创建一个使用 SHA-1 算法的 hash object,而另一种更快的方法是使用特定的函数直接创建,例如 hashlib.sha1()
。
至于 hash object,主要方法不外乎 update
(添加被哈希的数据)和 digest
(取哈希值的二进制表示)、hexdigest
(取哈希值的十六进制表示)。
行李
所谓 Python 与 C Struct 交互的说法可能说得比较玄乎,也许可以描述成 Python 值与二进制数据的相互转换吧。
struct.pack(fmt, v1, v2, ...)
即将 v1
、v2
等数据以 fmt
规定的形式转换为二进制数据。而 struct.unpack(fmt, string)
反之,是将二进制数据解释到若干个 Python 值。
顺带一提,Lua 也有类似的模组:http://www.inf.puc-rio.br/~roberto/struct/
地图
接下来,string.maketrans(from, to)
的大意是返回一个长度为 256 的字符串作映射表用(可以提供给 string.translate
使用,表示将 ASCII 为 N 的字符映射到字符串中的第 N 个字节),其中已经把 from
中的每一个字节映射到了 to
里的相应位置。
题外话,Python 中的字符串求长度是没有 length
方法的(虽然有 __len__
),只有一个 len
函数统一对各种可以求长度的对象求长度。这个让我想起了 C++11 中建议将 vector::begin
改为使用 ::begin
的做法。
阅读理解
List(列表)表示一个可变的序列。创建 List 可以使用方括号:
L = [] # 空
L = [expression, ...]
也可以使用 list
函数:
L = list() # 空
L = list(sequence)
更可以使用让 Python 做阅读理解的方法(好吧,是 List Comprehensions)。
正如喆哥在 Pipeline 中所说,将一个集合变换到另一个集合是一种非常常见的操作。Python 提供了 List Comprehensions 来提供这一机能:通过类似 [expression for variable in sequence]
的语法产生一个新的 List ,使得其中每一项都是满足后面「for 和 if 的组合」的 expression
。举个栗子:
>>> [(x, x**2) for x in range(6)]
[(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]
另外需要顺带一提的是,Python 的 for
循环只有类似 foreach 的 for x in y
形式。
列表排序
终于有一个正常向的小标题了 >.<
使用全局的 sorted
函数可以返回排序后的列表。而如果需要就地排序,可以使用 List 类型自带的 list.sort
方法来进行。
a = [5, 1, 4, 3]
print sorted(a) # [1, 3, 4, 5]
print a # [5, 1, 4, 3]
可以通过给出其它参数来对排序过程进行详细控制,比如:
a = ['an', 'Apple', 'is', 'good']
print sorted(a) # ['Apple', 'an', 'good', 'is']
print sorted(a, key=str.lower) # ['an', 'Apple', 'good', 'is']
print sorted(a, reverse=True) # ['is', 'good', 'an', 'Apple']
也可以用 lambda 定义用于比较的函数:
a = ['an', 'Apple', 'is', 'good']
print sorted(a, lambda x,y: cmp(str.lower(x), str.lower(y))) # 效果和上面使用 key 的例子相同
古董
曾几何时的 Visual Basic 中就有这么一对函数:Chr
和 Asc
,分别用于将 ASCII 值转为字符、将字符转为 ASCII 值。
而到了 Python 中,就是 chr
和 ord
函数,不同的是,针对 Unicode 还有一个 unichr
。
开膛破肚
对 List 除了可以使用下标进行普通的 index 操作外,还有一种名为 slice 的操作,使用「slice notation」表示:起始下标:结束下标:步长
。
yuruyuri = ['akari', 'kyouko', 'yui', 'chinatsu']
print yuruyuri[1] # 'kyouko'
print yuruyuri[1:3] # ['kyouko', 'yui']
print yuruyuri[1:-1] # ['kyouko', 'yui']
print yuruyuri[1::2] # ['kyouko', 'chinatsu']
可以看出,结束下标是不包含在最终结果里的哟。另外,每一个数字都可以省略:省略起始下标则默认为 0,省略结束下标则默认为全长,省略步长则默认为 1。
而对 slice 的直接赋值,会对原 List 造成修改:
yuruyuri[0:1] = []
print yuruyuri # ['kyouko', 'yui', 'chinatsu']
yuruyuri[0:1][0] = ''
print yuruyuri # ['kyouko', 'yui', 'chinatsu']
题外话,「slice notation」还可以用在字符串上,使得产生一个字串。而由于 Python 的字符串不像 C 的字符串,是不可以通过 s[2] = 'a'
更改内容的,于是通过 slice 来进行就方便多了。(s[:n] + s[n:] == s
哟。)
天下大势
将字符串拆分为子字符串列表、将字符串列表合并为一个字符串,这些也是常见操作。Python 中实现这种机能的函数分为两组:
str.join(iterable)
和str.split([split [,maxsplit]])
string.join(list [,sep])
和string.split(s [,sep [,maxsplit]])
其实都是一样的作用,只是前者是内置字符串类的方法,后者是 string
模组的函数。
红色警戒 II
类似于 C++ 的 RAII 和 C# 的 using
,Python 有 with
语句。
with
使用__enter__
和__exit__
函数using
使用IDispose
接口- RAII 使用构造函数和析构函数
熟悉的应该一看就懂了吧~(虽然我不清楚三者是否可以等价,但从效果上说还是差不多的嘛~)
你好,关注你有几日了,你最近一直在跟PM对着干,这从你的跟贴和签名档中表露无遗。我感兴趣这是为什么,是纯属茶余饭后的活动筋骨还是实在看不下眼而打抱不平:)《C伴侣》这本书是我策划的,原本抱着很大的希望,希望给受谭浩强这本书影响的读者解惑。但对由于我在策划上犯的错误,和作者方面的原因(既有认识上和责任心方面,也有身体方面的原因),最终导致这本书的失败。即使没有PM,这本书也会失败,因为不管从内容还是质量上,这本书远没有达到我的初衷和要求。你认真回复的态度,说实话,让我蛮感动得。如果看中图灵的什么书,可以跟我说,我送给你。我的QQ:362253039
你好~单纯觉得有些看不下去罢了……虽然书里确实有硬伤,但可以看得出来本意是好的,谁能保证自己没有好心办坏事的时候呀。我觉得 PM 的帖子里有很多是带着有色眼镜看问题或者干脆故意找茬,所以他有些说的做的过分的地方实在是忍不住想指出 ^_^