500lines or less 这个系列看起来很好,但是无奈本人实在是学不动。。国庆一天尝试了3个发现都很困难。。一个是代码长度一高,加上语言不通,很容易导致逻辑混乱。一个可能是本人实在是对这方面缺乏足够的兴趣,不管怎么说,可能是现在的我太弱了吧 -2016年国庆
__getitem__ 和 __setitem__ 是两个类的特殊方法
比如一个类叫DBDB
那么a=DBDB(f)
a[4] 就等价于a.__getitem__(4)
__setitem__方法同理
__future__:引入下一个版本的函数
__all__:在模块(*.py)中使用意为导出__all__列表里的类、函数、变量等成员,
否则将导出modualA中所有不以下划线开头(私有)的成员,
在模块中使用__all__属性可避免在相互引用时的命名冲突
以下内容来自:http://www.cnblogs.com/windlazio/archive/2013/01/24/2874417.html
使用raise抛出异常 当程序出现错误,python会自动引发异常,也可以通过raise显示地引发异常。一旦执行了raise语句,raise后面的语句将不能执行。
@classmethod : 类方法
@staticmethod : 静态方法
类方法和静态方法的调用一样,都是通过类就可以直接调用。
区别:类方法,需要传入该类,定义类方法的时候要传一个默认的参数cls。静态方法则不用。cls它表示这个类本身。
一般的文件流操作都包含缓冲机制,write方法并不直接将数据写入文件,而是先写入内存中特定的缓冲区。
flush方法是用来刷新缓冲区的,即将缓冲区中的数据立刻写入文件,同时清空缓冲区。
正常情况下缓冲区满时,操作系统会自动将缓冲数据写入到文件中。
至于close方法,原理是内部先调用flush方法来刷新缓冲区,再执行关闭操作,这样即使缓冲区数据未满也能保证数据的完整性。
如果进程意外退出或正常退出时而未执行文件的close方法,缓冲区中的内容将会丢失。
以下是seek()方法的语法:
参数
def _seek_end(self):
self._f.seek(0, os.SEEK_END)
int
,
float
,
str
,
list
,
dict
和
tuple
。不同于编译型语言 C/C++,在 Python 中,我们往往不需要关心不同类型的变量在解释器内部的实现方式。例如,对于一个长整形数据,我们在 Python 2 中可以直接写成
a=123456789012345L
,而不用去考虑变量
a
占了几个字节。这种抽象的方式为程序的编写提供了足够的支持,但是在某些情况下(比如读写二进制文件,进行网络 Raw Socket 编程)的时候,我们需要一些其他模块来实现我们关于变量长度控制的需求。
当我们在 Python 中跟二进制数据打交道的时候,就要用到 struct
这个模块了。struct
模块为 Python 与 C 的混合编程,处理二进制文件以及进行网络协议交互提供了便利。理解这个模块主要需要理解三个函数:
1 2 3 |
struct.pack(fmt, v1, v2, ...) struct.unpack(fmt, string) struct.calcsize(fmt) |
第一个函数 pack
负责将不同的变量打包在一起,成为一个字节字符串,即类似于 C 语言中的字节流。第二个函数 unpack
将字节字符串解包成为变量。第三个函数 calsize
计算按照格式 fmt 打包的结果有多少个字节。这里打包格式 fmt 确定了将变量按照什么方式打包成字节流,其包含了一系列的格式字符串。这里就不再给出不同格式字符串的含义了,详细细节可以参照 Python Doc (struct).
一般而言,在使用 struct 的时候,要打包的数据都是定长的。定长的数据代表你需要明确给出要打包的或者解包的数据长度,否则打包解包函数将会出错。下面用例子说明什么是定长打包:
1 2 3 4 5 6 7 8 |
import struct a = struct.pack("2I3sI", 12, 34, "abc", 56) b = struct.unpack("2I3sI", a) print b ## 输出 (12, 34, 'abc', 56) |
上面的代码将两个整数 12 和 34,一个字符串 “abc” 和一个整数 56 一起打包成为一个字节字符流,然后再解包。其中打包格式中明确指出了打包的长度:"2I"
表明起始是两个unsigned int
,"3s"
表明长度为4的字符串,最后一个 "I"
表示最后紧跟一个 unsigned int
。所以上面的打印 b 输出结果是:(12, 34, ‘abc’, 56)。
我们可以调用 calcsize()
来计算 "2I3sI"
这个模式占用的字节数:
1 2 |
print struct.calcsize("2I3sI") ## 输出 16 |
可以看到上面的三个整型加一个 3 字符的字符串一共占用了 16 个字节。为什么会是 16 个字节呢?不应该是 15 个字节吗?其实,在 struct
的打包过程中,根据特定类型的要求,必须进行字节对齐。由于默认unsigned int
型占用四个字节,因此要在字符串的位置进行4字节对齐,因此即使是 3 个字符的字符串也要占用 4 个字节。
再看一下不需要字节对齐的模式:
1 2 |
print struct.calcsize("2Is") ## 输出 9 |
由于单字符出现在两个整型之后,不需要进行字节对齐,所以输出结果是 9.
需要指出的是,对于 unpack
而言,只要 fmt
对应的字节数和字节字符串 string
的字节数一致,就可以成功的进行解析,否则 unpack
函数将抛出异常。例如我们也可以使用如下的 fmt
解析出 a
:
1 2 3 4 5 |
c = struct.unpack("2I2sI", a) print struct.calcsize("2I2sI") print c ## 输出 16 (12, 34, 'ab', 56) |
可以看到这里 unpack
解析出了字符串的前两个字符,没有产生任何问题。
在上一节的介绍中,我们看到了在使用 pack
和 unpack
的过程中,我们需要明确的指出打包模式中每个位置的长度。比如格式 "2I3sI"
就明确指出了整型的个数和字符串的个数。有时候,我们还可能会需要处理变长的打包数据。
例如我们在程序中可能会得到一个字符串 s,这个 s 没有一个固定的长度,所以我们每次打包的时候都需要将 s 的长度也打包到一起,这样我们才能进行正确的解包。其实,这种情况在处理网络数据包中非常常见。在使用网络编程的时候,我们可能利用报文的第一个字段记录报文的长度。每次读取报文的时候,我们先读取报文的第一个字段,获取其长度之后在处理报文内容。
我们可以采用两种方式处理这种情况:
1 2 |
s = bytes(s, 'utf-8') # Or other appropriate encoding struct.pack("I%ds" % (len(s),), len(s), s) |
或者
1 |
struct.pack("I", len(s)) + s |
第一种方式先将报文转变成为字节码,然后获取字节码的长度,将长度嵌入到打包之后的报文中去。可以看到格式字符串中的 "I"
就用来记录报文的长度。第二种方式是直接将字符串的长度打包成字节字符串,再跟原始字符串做一个连接操作。
根据上面的打包方式,我们可以轻松的解开打包串:
1 2 3 |
int_size = struct.calcsize("I") (i,), data = struct.unpack("I", data[:int_size]), data[int_size:] data_content = data[i:] |
由于报文的长度 len(s)
我们使用定长的整型 "I"
进行了打包,所以解包的时候我们可以先将报文长度获取出来,之后再根据报文长度读取报文内容。
struct.
pack
(
fmt,
v1,
v2,
...
)
Return a string containing the values v1, v2, ...
packed according to the given format. The arguments must match the values required by the format exactly.
struct.
unpack
(
fmt,
string
)
Unpack the string (presumably packed by pack(fmt, ...)
) according to the given format. The result is a tuple even if it contains exactly one item. The string must contain exactly the amount of data required by the format (len(string)
must equal calcsize(fmt)
).
By default, C types are represented in the machine’s native format and byte order, and properly aligned by skipping pad bytes if necessary (according to the rules used by the C compiler).
Alternatively, the first character of the format string can be used to indicate the byte order, size and alignment of the packed data, according to the following table:
Character | Byte order | Size | Alignment |
---|---|---|---|
@ |
native | native | native |
= |
native | standard | none |
< |
little-endian | standard | none |
> |
big-endian | standard | none |
! |
network (= big-endian) | standard | none |
If the first character is not one of these, '@'
is assumed.
Native byte order is big-endian or little-endian, depending on the host system. For example, Intel x86 and AMD64 (x86-64) are little-endian; Motorola 68000 and PowerPC G5 are big-endian; ARM and Intel Itanium feature switchable endianness (bi-endian). Use sys.byteorder
to check the endianness of your system.
Native size and alignment are determined using the C compiler’s sizeof
expression. This is always combined with native byte order.
Standard size depends only on the format character; see the table in the Format Characters section.
Note the difference between '@'
and '='
: both use native byte order, but the size and alignment of the latter is standardized.
The form '!'
is available for those poor souls who claim they can’t remember whether network byte order is big-endian or little-endian.
There is no way to indicate non-native byte order (force byte-swapping); use the appropriate choice of '<'
or '>'
.
Notes:
Format characters have the following meaning; the conversion between C and Python values should be obvious given their types. The ‘Standard size’ column refers to the size of the packed value in bytes when using standard size; that is, when the format string starts with one of '<'
, '>'
, '!'
or '='
. When using native size, the size of the packed value is platform-dependent.
Format | C Type | Python type | Standard size | Notes |
---|---|---|---|---|
x |
pad byte | no value | ||
c |
char |
string of length 1 | 1 | |
b |
signed char |
integer | 1 | (3) |
B |
unsigned char |
integer | 1 | (3) |
? |
_Bool |
bool | 1 | (1) |
h |
short |
integer | 2 | (3) |
H |
unsigned short |
integer | 2 | (3) |
i |
int |
integer | 4 | (3) |
I |
unsigned int |
integer | 4 | (3) |
l |
long |
integer | 4 | (3) |
L |
unsigned long |
integer | 4 | (3) |
q |
long long |
integer | 8 | (2), (3) |
Q |
unsigned long long |
integer | 8 | (2), (3) |
f |
float |
float | 4 | (4) |
d |
double |
float | 8 | (4) |
s |
char[] |
string | ||
p |
char[] |
string | ||
P |
void * |
integer | (5), (3) |
原文:http://aosabook.org/en/500L/dbdb-dog-bed-database.html