TimothyQiu's Blog

keep it simple stupid

SS 源码阅读小记

分类:技术

阅读一下某源代码,学习一些 Python 的基本知识 = =

注意:以下内容均为 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, ...) 即将 v1v2 等数据以 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 中就有这么一对函数:ChrAsc,分别用于将 ASCII 值转为字符、将字符转为 ASCII 值。

而到了 Python 中,就是 chrord 函数,不同的是,针对 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 中实现这种机能的函数分为两组:

其实都是一样的作用,只是前者是内置字符串类的方法,后者是 string 模组的函数。

红色警戒 II

类似于 C++ 的 RAII 和 C# 的 using,Python 有 with 语句。

熟悉的应该一看就懂了吧~(虽然我不清楚三者是否可以等价,但从效果上说还是差不多的嘛~)

Python

已有 2 条评论 »

  1. 你好,关注你有几日了,你最近一直在跟PM对着干,这从你的跟贴和签名档中表露无遗。我感兴趣这是为什么,是纯属茶余饭后的活动筋骨还是实在看不下眼而打抱不平:)《C伴侣》这本书是我策划的,原本抱着很大的希望,希望给受谭浩强这本书影响的读者解惑。但对由于我在策划上犯的错误,和作者方面的原因(既有认识上和责任心方面,也有身体方面的原因),最终导致这本书的失败。即使没有PM,这本书也会失败,因为不管从内容还是质量上,这本书远没有达到我的初衷和要求。你认真回复的态度,说实话,让我蛮感动得。如果看中图灵的什么书,可以跟我说,我送给你。我的QQ:362253039

    1. 你好~单纯觉得有些看不下去罢了……虽然书里确实有硬伤,但可以看得出来本意是好的,谁能保证自己没有好心办坏事的时候呀。我觉得 PM 的帖子里有很多是带着有色眼镜看问题或者干脆故意找茬,所以他有些说的做的过分的地方实在是忍不住想指出 ^_^

添加新评论 »