2009年6月28日星期日

无题

工作到了今天,看到了很多,也想到了很多,其实感觉自己一路走来还是不容易。刚工作的时候的心态还是很稚嫩,其实一直到今天自己还是在不停地摸索,怎么去完善自己的情商。其实我一直觉得,知识,尤其是工作上的知识,要掌握下来是不难的。我觉得更难得是怎么去让自己的思考方式比别人更加好,这更是一条更难跨越的沟壑。无论什么知识,其实你能掌握的,别人比你花个多两倍,三倍的时间,总也能掌握到得,但是一个人比别人的“能力”显得更强,更多的是这个人在一个领域,一个问题上是否能思考得更加深入,能够更多地从多个方面去切入问题的核心来思考。
到了今时今日,我当然深知自己的知识体系还是有很大的不足,相对于很多ACM牛人,我的解题能力不足,相对于在此领域探索很多年的人,我的经验,我的思考方式还是有很大的不足。怎么能够从各个方面发挥自己的能力,能更好地进步呢?这应该是成为我以后几年一直思考的问题。
回想自己的职业之路,只工作了一年便跳槽显然并不是最好的选择,另外跳的对象也并不是一个很好的平台。虽然自己一直认为自己一定会走上创业这条路,但是现在自己却越来越觉得还是更喜欢和技术打交道,还是希望自己能在一个很好的平台上去做自己喜欢的事情,现在,显然我还没找到这样一个平台。

2009年5月1日星期五

InnoDB和MyISAM的差别[zz]

InnoDB和MyISAM是在使用MySQL最常用的两个表类型,各有优缺点,视具体应用而定。基本的差别为:MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持。MyISAM类型的表强调的是性能,其执行数度比InnoDB类型更快,但是不提供事务支持,而InnoDB提供事务支持已经外部键等高级数据库功能。

MyIASM是IASM表的新版本,有如下扩展:
二进制层次的可移植性。
NULL列索引。
对变长行比ISAM表有更少的碎片。
支持大文件。
更好的索引压缩。
更好的键码统计分布。
更好和更快的auto_increment处理。

以下是一些细节和具体实现的差别:

1.InnoDB不支持FULLTEXT类型的索引。
2.InnoDB 中不保存表的具体行数,也就是说,执行select count(*) from table时,InnoDB要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可。注意的是,当count(*)语句包含 where条件时,两种表的操作是一样的。
3.对于AUTO_INCREMENT类型的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中,可以和其他字段一起建立联合索引。
4.DELETE FROM table时,InnoDB不会重新建立表,而是一行一行的删除。
5.LOAD TABLE FROM MASTER操作对InnoDB是不起作用的,解决方法是首先把InnoDB表改成MyISAM表,导入数据后再改成InnoDB表,但是对于使用的额外的InnoDB特性(例如外键)的表不适用。

另外,InnoDB表的行锁也不是绝对的,如果在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表,例如update table set num=1 where name like “%aaa%”

任何一种表都不是万能的,只用恰当的针对业务类型来选择合适的表类型,才能最大的发挥MySQL的性能优势。

2009年2月18日星期三

[zt]C++中的typename关键字(想哪儿说哪儿)

可能是C++的设计者(BJ?)觉得没用必要引入更多的关键字,其实模板刚刚引入C++中的时候并没有typename关键字。那时候定义类模板的类型参数通常使用class关键字。如:
template
class Test
{
public :
T t;
.....
};
随着模板应用的推广,大家发现使用typedef非常关键,因为实例化后的模板定义通常很长,通过使用typedef可以有效的缩短代码长度。如:
class UseTest
{
public:
typedef Test intTT;
...
};
这时问题就来了,当我写UseTest::intTT,这个intTT究竟是UseTest的一个静态成员(static)还是一个类型呢?所以typename关键字就引入了C++。
所以在定义一个intTT的对象时,我们就要这样写:
typename UseTest::intTT int_tt_obj;
通过typename明确指出intTT是一个类型而不是一个静态成员。
C++中的typename关键字(想哪儿说哪儿)

2009年1月19日星期一

python Unicode I/O

在系统内部, Unicode 字符串被表示为一个16位整数序列,8-bit 字符串则是一个字节序列, 绝大多数字符串操作被扩展为能够处理更宽范围的字符值。只要 Unicode 字符串被转换为字节流,就必然会产生一系列问题(需要解决)。首先,要考虑现有软件的兼容性, 对那些仅支持 ASCII或其它 8-bit的软件来说,将 Unicode字符串转化为 ASCII字符串是较好的方法。其次, 16-bit 字符占用两个字节,字节顺序问题虽然比较无聊但必须考虑。对一个Unicode字符 U+HHLL 来说, 小端法编码方案将低位字节放在前面, 即 LL HH;大端法编码方案则将高位字节放在前面,即 HH LL. 就因为这么点问题, 不指定编码方案,你就无法将原始 Unicode 数据写入文件.

要解决这些问题, 只能根据特定的编码规则将 Unicode 字符串进行客观表示。这些规则定义了如何将 Unicode 字符表示为字节序列。在第四章, 针对 unicode()及 s.encode() 首先介绍了编码规则。举例来说:
Toggle line numbersToggle line numbers

1 a = u"M\u00fcller"
2 b = "Hello World"
3 c = a.encode('utf-8') # Convert a to a UTF-8 string
4 d = unicode(b) # Convert b to a Unicode string

codecs 模块用类似的技术解决了 Unicode 的输入输出问题。 codecs 模块拥有一系列转换函数依据不同的编码方案完成字节数据和 Unicode 字符串的转换。通过调用 codecs.lookup(encoding) 函数来选择一种编码方案。这个函数返回一个包括四个元素的 tuple (enc_func, decode_func, stream_reader, stream_writer ). 举例来说:
Toggle line numbersToggle line numbers

1 import codecs
2 (utf8_encode, utf8_decode, utf8_reader, utf8_writer) = \
3 codecs.lookup('utf-8')

enc_func (u [,errors ]) 函数接受一个 Unicode 字符串 u ,返回值是tuple(s , len).其中 s 是转码后的 8-bit 字符串(内容为 u 的一部分或全部), len 是被成功转换的 Unicode 字符数. decode_func(s [,errors]) 函数接受一个 8-bit 字符串,返回值是 tuple(u, len)。其中 u 是一个 Unicode字符串(内容为 s 的一部分或全部),len 是被成功转换的字符数。errors 决定转化过程中的错误如何处理,它的值可能是 'strict' 或 'ignore' 或 'replace'。若是 'strict'模式, 编码错误将引发 UnicodeError 异常。 若是 'ignore' 模式, 编码错误将被忽略。若是 'replace' 模式,无法转换的编码将被替换为 '?' 字符(Unicode字符U+FFFD或8-bit字符 '?')。

stream_reader 用来对文件对象进行封装,以支持 Unicode 数据读取. 调用 stream_reader (file) 返回封装后的文件对象,它的 read(), readline(), 及 readlines() 方法支持读取 Unicode 字符串数据. stream_writer 用来对文件对象进行封装,以支持将 Unicode 字符串写入文件。调用 stream_writer(file) 返回封装后的文件对象,它的 write() 和 writelines() 方法将 Unicode 字符串按给定的编码转换为字节流写入文件中。

下面的例子演示了如何使用这些方法处理 UTF-8 编码的 Unicode 数据:
Toggle line numbersToggle line numbers

1 # 输出 Unicode 数据到文件
2 ustr = u'M\u00fcller' # 一个Unicode 字符串
3
4 outf = utf8_writer(open('foo','w')) # 创建 UTF-8 字节流
5 outf.write(ustr)
6 outf.close()
7
8 # 从一个文件读取 unicode 数据
9 infile = utf8_reader(open('bar'))
10 ustr = infile.read()
11 infile.close()

当处理 Unicode文件时, 数据编码通常内嵌在文件本身当中。举例来说,XML 解析器根据文件的前几个字节'' 来判断文件编码. 如果最初的四个值是 3C 3F 78 6D ('


用类似下面的代码来读取文档的编码:
Toggle line numbersToggle line numbers

1 f = open("somefile")
2 # Determine encoding
3 ...
4 (encoder,decoder,reader,writer) = codecs.lookup(encoding)
5 f = reader(f) # Wrap file with Unicode reader
6 data = f.read() # Read Unicode data
7 f.close()

1.6.1. Unicode 数据编码

表 9.2 列出了codecs模块中目前正在使用的所有编码

表 9.2. codecs 模块中的全部编码器

编码 描述
'ascii' ASCII 编码
'latin-1', 'iso-8859-1' Latin-1 或 ISO-8859-1 编码
'utf-8' 8-bit 变长编码
'utf-16' 16-bit 变长编码
'utf-16-le' UTF-16, 显式小端编码方案
'utf-16-be' UTF-16, 显式大端编码方案
'unicode-escape' 和 u"string " 格式相同
'raw-unicode-escape' 和 ur"string "格式相同

下面的段落描述了各种编码的细节:

'ascii' 编码:

'ascii' 编码, 字符值的范围被限制在[0,0x7f] 和 [U+0000, U+007F]。超出这个范围的任何字符都是非法的。

'iso-8859-1' 或 'latin-1' 编码:

字符可以是任意的 8-bit 值([0,0xff] 及 [U+0000, U+00FF]). 取值范围 [0,0x7f] 内的字符对应 ASCII 字符集,取值范围 [0x80,0xff] 内的字符对应 ISO-8859-1 或 扩展 ASCII 字符集。超出 [0,0xff] 取值范围的任何字符都会造成错误。

'utf-8' 编码:

UTF-8 是一种变长编码,它能表示所有的Unicode字符。一个单独的字节用来表示值为 0–127 的 ASCII 字符。所有其它字符均被表示为多字节序列(双字节或3字节)。这些字节的编码见下表

Unicode 字符 Byte 0 Byte 1 Byte 2
U+0000 - U+007F 0nnnnnnn
U+007F - U+07FF 110nnnnn 10nnnnnn
U+0800 - U+FFFF 1110nnnn 10nnnnnn 10nnnnnn

对两字节序列, 第一个字节的前三个比特总是 110. 对三字节序列, 第一个字节的前三个比特总是 1110. 多字节序列的所有后来字节的前两个比特都是 10。

UTF-8 格式一个字符最多可以使用六个字节。 Python 中, 四字节 UTF-8 序列被称为代理对,用来对一对 Unicode 字符进行编码。这一对字符的取值都在[U+D800, U+DFFF]范围内并组合成一个 20-bit 的值. 代理对这样编码:四字节序列 111100nn 10nnnnnn 10nnmmmm 10mmmmmm 被编码成这样一对: U+D800 + N , U+DC00 + M , 其中 N 是高10位, M 是低十位。五字节和六字节 UTF-8 序列(开始位分别为 111110 和 1111110) 用来对32比特值的Unicode字符进行编码。Python目前不支持五字节和六字节UTF-8序列。如果数据流中存在这样的数据会引发 UnicodeError 异常。

UTF-8 编码对旧程序支持的相当好. 首先,标准 ASCII 字符的编码没有发生任何改变。这意味着 UTF-8 编码的 ASCII 字符串与传统的 ASCII 字符串完全相同。其次, UTF-8 编码的多字节序列未内嵌 null 字节。这样现有的基于 C 库的软件和程序所使用的 null-结尾的 8-bit 字符串可以与 UTF-8 字符串相容. 最后,UTF-8 编码 保留了字符串的字典顺序。也就是说如果 a 和 b 是 Unicode 字符串并且 a < b, 则当 a 和 b被转化为UTF-8编码后, a < b 仍然成立。因此,写给 ASCII 字符串的排序算法及其它与顺序有关的算法也一样可以工作在 UTF-8 编码上。

'utf-16' , 'utf-16-be' , and 'utf-16-le' 编码:

UTF-16 是一种变长16位编码,其中 Unicode 被记录为 16-bit 值。如果未指定字节顺序,则默认为大端法编码方案。另外,一个特殊的字符 U+FEFF 可以用来显式的标记UTF-16 数据流的字节顺序。.大端编码方案, U+FEFF 字符表示 zero-width nonbreaking space, 而 U+FFFE 则是一个非法的 Unicode字符。因此,编码器可以使用这个字节顺序 FE FF 或 FF FE 来判断字节顺序。当读取 Unicode 数据时,Python会自动移去这个标志。

'utf-16-be' 编码 显式指定届UTF-16 大端编码(big endian), 'utf-16-le' 显式指定 UTF-16 小端编码(little ending)。

尽管已经有多种 UTF-16 的扩展以支持更多字符,目前的 Python 并不支持任何这样的扩展。

'unicode-escape' 及 'raw-unicode-escape' 编码:

这些编码方法被用来转换 Unicode 字符串到 Python使用的 Unicode 字符串及原始Unicode字符串。举例来说:
Toggle line numbersToggle line numbers

1 s = u'\u14a8\u0345\u2a34'
2 t = s.encode('unicode-escape') #t = '\u14a8\u0345\u2a34'

1.6.2. Unicode 字符属性
除了实现输入输出之外, 使用 Unicode 的程序必然会有测试 Unicode 字符属性的需要(是否大小写、是否数字、是否空白等等)。 unicodedata 模块提供了这些 unicode字符数据库。. 常规字符属性可以通过 unicodedata.category(c) 函数得到. 例如, unicodedata.category(u"A") 返回 'Lu', 表示这个字符是一个大写字符。更多关于Unicode 字符数据库及 unicodedata 模块的细节,请参阅附录A。