本篇文章介绍的这些Python方法(也可以称为Python函数),很多既可以用于普通字符串对象,又可以用于unicode字符串对象。但是为了方便起见,作者只会给出普通字符串对象相关的C源码(也就是定义在Objects/stringobject.c文件中的代码)...
函数名 | 相关描述 |
---|---|
S.capitalize() |
这里S表示字符串对象,该方法会创建一个S的copy(拷贝), 同时将copy字符串的首字母设置为大写, 余下的其他字母都设置为小写。最后将该copy返回。 |
S.center(width[, fillchar]) |
当center方法的width参数小于等于S的字符个数时,就直接将S返回。 当width参数大于S的字符个数时,就会创建一个S的copy(拷贝), 并在copy字符串的左右两侧填充fillchar字符,如果fillchar没提供的话, 默认就使用空格符来填充,通过左右填充让copy字符串能居中对齐。 最后将这个copy字符串对象返回。 |
S.count(sub[, start[, end]]) |
该方法会在S字符串对象里统计sub子字符串的个数,start与end是可选的参数,用于确定 S字符串对象的查找范围,相当于在S[start:end]中统计sub的个数。 |
S.decode([encoding[,errors]]) |
该方法里的两个参数都是可选的,该方法会将字符串S根据encoding参数进行解码操作, 例如,当encoding为base64时,就可以将字符串按照base64进行解码。errors参数用于 设置当解码出错时的处理方式,例如当errors为ignore时,解码出错时会忽略错误继续执行。当 errors为strict时,会抛出相关的异常。strict是errors参数的缺省值。 返回的是一个新的解码后的字符串对象。 |
S.encode([encoding[,errors]]) |
该方法会将字符串S根据encoding参数,进行编码操作。返回的是一个新的编码后的字符串对象。 |
S.endswith(suffix[, start[, end]]) |
该方法的start与end参数是可选的,用于检测S[start:end]字符串是否是以suffix子字符串结尾的。 |
S.expandtabs([tabsize]) |
该方法会返回S的一个copy(拷贝),并将copy字符串里的所有的tab制表符, 都根据tab边界替换为特定数量的空格符, tabsize参数是可选的,用于指定tab边界的字符宽度,tabsize的缺省值为8 。 |
S.find(sub [,start [,end]]) |
该方法的start与end参数是可选的,用于在S[start:end]中查找sub子字符串,如果找到了sub, 就返回sub在S里的偏移值(注意是S里的偏移值,而不是S[start:end]里的偏移值,下面会举例说明), 如果找不到,则返回-1 。 |
S.index(sub [,start [,end]]) |
该方法也是在S[start:end]中查找sub子字符串,但是与find方法的区别在于:当index方法找不到 sub子字符串时,会抛出ValueError异常,而不会像find那样返回-1。 |
S.isalnum() |
该方法用于检测字符串S里的所有字符,是否都是字母或数字。如果都是字母或数字,就返回True。 如果其中有一个字符不是字母或数字的话,则返回False 。 |
S.isalpha() |
如果S里的所有字符都是字母的话(S中必须至少有一个字符),该方法就返回True, 否则返回False 。 |
S.isdigit() |
如果S里的所有字符都是数字的话(S中必须至少有一个字符),该方法就返回True, 否则返回False 。 |
S.islower() |
如果S中所有大小写敏感的字符都是小写的话(S中必须至少包含一个大小写敏感的字符),该方法 就返回True,否则返回False 。 |
S.isnumeric() |
这里的S必须是unicode字符串,因为isnumeric方法只存在于unicode字符串对象中。 该方法用于判断字符串里的字符是否都是NUMERIC数字类型,要判断一个unicode字符是否是 数字类型,是由该字符对应的_PyUnicode_TypeRecord结构 (该结构位于python源码的Objects/unicodectype.c文件中)的flags字段来决定的,当flags字段存在 NUMERIC_MASK二进制位时,对应的字符就是NUMERIC数字类型。 例如,u'四'就是NUMERIC数字类型。前缀u表示'四'为unicode编码的字符串。因此, u'四'.isnumeric()在执行时,就会返回True 。 |
S.isspace() |
该方法用于判断S里的所有字符是否都是whitespace(空白符),空白符可以是:空格符,\f(换页符), \n(换行符),\r(回车符),\t(水平制表符),以及\v(垂直制表符)。 |
S.istitle() |
该方法用于判断S是否是标题样式的字符串。标题样式的字符串里,每个单词除了首字母是大写字母外, 单词的其余部分都是小写字母。字符串中的非大小写敏感的字符则用于分隔单词,像空格符和数字等 都是非大小写敏感的(也就是没有大小写的),它们就可以用来分隔单词。 例如:'Hello World123Android'就是标题样式的字符串,该字符串中的空格符和数字123,将其分隔为 Hello,World及Android三个单词,每个单词都是以大写字母开头,单词的其余部分为小写字母,因此, 'Hello World123Android'.istitle()在执行时,就会返回True 。 |
S.isupper() |
如果S中所有大小写敏感的字符都是大写的话(S中必须至少包含一个大小写敏感的字符),该方法 就返回True,否则返回False 。 |
S.join(iterable) |
将iterable(可迭代的集合,如列表等)里的所有字符串成员连接在一起,构成一个新的字符串进行返回, 字符串成员之间通过S字符串来作为分隔符。 例如:'--'.join(['aa','bb','cc','ddd'])语句执行后,返回的结果就是:'aa--bb--cc--ddd' |
len(object) |
该函数并非字符串对象的方法,它是属于内建模块里的函数。当对字符串对象执行该函数时,就可以 返回字符串里的字符个数。例如:len('hello')执行的结果就是5,也就是'hello'字符串里包含5个字符。 |
S.ljust(width[, fillchar]) |
当ljust方法的width参数小于等于S的字符个数时,就直接将S返回。 当width参数大于S的字符个数时,就会创建一个S的copy(拷贝), 并在copy字符串的右侧填充fillchar字符,如果fillchar没提供的话, 默认就使用空格符来填充,通过右侧填充让copy字符串能进行左对齐。 最后将这个copy字符串对象返回。 |
S.lower() |
该方法会创建一个S的copy(拷贝),同时将copy字符串里的所有大写字母都转为小写字母。 最后将该copy字符串对象返回。 |
S.lstrip([chars]) |
该方法会创建一个S的copy(拷贝),如果没提供chars参数的话,就将copy字符串左侧的 whitespace(空白符)都移除掉,如果提供了chars参数的话,则将copy字符串左侧的所有 存在于chars里的字符都移除掉。 例如:'++++----*****////***hello'.lstrip('+-*/') 执行的结果就是:'hello' ,lstrip方法将左侧的 + - * / 字符都移除掉了。 |
maketrans(frm, to) |
maketrans是string模块里的方法,使用前需要先导入该模块,该方法会返回一个包含256个 字符的字符串(相当于一个重新设定过的ASCII码表),该字符串可以作为字符串对象的translate 方法的参数,translate方法会根据这256个字符作为ASCII码表,然后将字符串里的字符转译为 别的字符,你可以将原始的字符串看成密文,将新的ASCII码表看成密码字典,将转译后的字符串 看成是明文。maketrans方法就是创建密码字典用的。下面会举例说明。 |
max(str) |
max是内建模块里的函数,当对字符串对象使用max方法时,该方法会将字符串里的ASCII码值最大的字符 进行返回。例如:max('abcd')返回的结果就是'd' |
min(str) |
min也是内建模块里的函数,当对字符串对象使用min方法时,该方法会将字符串里的ASCII码值最小的字符 进行返回。例如:min('abcd')返回的结果就是'a' |
S.replace(old, new[, count]) |
该方法会创建S的一个copy(拷贝),同时将copy字符串里的old子字符串都替换为new字符串。 如果没提供count参数,则全部都替换掉,如果提供了count参数,则只替换前count个old子字符串。 例1:'is is is'.replace('is','mn') 执行后,得到的结果就是:'mn mn mn' 例2:'is is is'.replace('is','mn', 2) 执行后的结果就是:'mn mn is' |
S.rfind(sub [,start [,end]]) |
rfind方法也是在S[start:end]里查找sub子字符串,与find方法所不同的是:rfind是从后往前反向进行查找。 如果找到了sub则返回sub在S里的偏移值,如果没找到,则返回-1 。 |
S.rindex(sub [,start [,end]]) |
类似于rfind方法,也是在S[start:end]里查找sub子字符串,只不过当rindex方法没找到sub时, 会抛出ValueError异常,而不会像rfind那样返回-1 。 |
S.rjust(width[, fillchar]) |
当rjust方法的width参数小于等于S的字符个数时,就直接将S返回。 当width参数大于S的字符个数时,就会创建一个S的copy(拷贝), 并在copy字符串的左侧填充fillchar字符,如果fillchar没提供的话, 默认就使用空格符来填充,通过左侧填充让copy字符串能进行右对齐。 最后将这个copy字符串对象返回。 |
S.rstrip([chars]) |
该方法会创建一个S的copy(拷贝),如果没提供chars参数的话,就将copy字符串右侧的 whitespace(空白符)都移除掉,如果提供了chars参数的话,则将copy字符串右侧的所有 存在于chars里的字符都移除掉。 例如:'hello---+++'.rstrip('+-') 执行的结果就是:'hello' ,该方法将字符串右侧的 所有 + 和 - 字符都移除掉了。 |
S.split([sep [,maxsplit]]) |
该方法会根据sep参数,将S进行分割,分割后的子字符串会形成一个列表,该列表会作为结果返回。 如果没提供sep参数的话,则使用whitespace(空白符)来进行分割。maxsplit参数用于表示分割次数, 如果没提供maxsplit参数的话,则将所有的sep都进行分割。 例1:'aa--bb--cc--dd'.split('--') 脚本执行后会返回 ['aa', 'bb', 'cc', 'dd'] 的列表,该列表就是 用'--' 分割后所形成的。 例2:'aa \n\rbb\f\fcc\v\v\rdd'.split() 脚本执行后也会返回 ['aa', 'bb', 'cc', 'dd'] ,当没提供sep参数时,就使用 whitespace(空白符)来进行分割。 例3:'aa--bb--cc--dd'.split('--', 2) 脚本执行后返回的结果为 ['aa', 'bb', 'cc--dd'] ,由于maxsplit参数的值 为2,因此,只对前两个'--'进行了分割。 |
S.splitlines(keepends=False) |
该方法会将S里的多行字符串,根据换行符进行分割,分割所形成的列表作为结果返回。 如果keepends参数为True的话(默认是False),则列表里的字符串成员会保留换行符。 例1:'hello\r\nhell\nhello'.splitlines() 执行后返回的是:['hello', 'hell', 'hello'] 例2:'hello\r\nhell\nhello'.splitlines(True) 执行后返回的是:['hello\r\n', 'hell\n', 'hello'] 例3:'hello\r\nhell\nhello'.splitlines(3) 返回的也是:['hello\r\n', 'hell\n', 'hello'] ,这里不为0的数字,也 会被当作True 。 |
S.startswith(prefix[, start[, end]]) |
该方法的start与end参数是可选的,用于检测S[start:end]字符串是否是以prefix子字符串开头的。 例1:'hello'.startswith('he') 返回的结果是:True 例2:'hello'.startswith(('xe', 'he')) 返回的结果也是True,startswith方法还可以接受元组作为参数, 用于判断字符串的开头是否是以元组里的某个字符串开头的。 |
S.strip([chars]) |
该方法会创建一个S的copy(拷贝),如果没提供chars参数的话,就将copy字符串左右两侧的 whitespace(空白符)都移除掉,如果提供了chars参数的话,则将copy字符串左右两侧的所有 存在于chars里的字符都移除掉。 例如:'--++hello--++'.strip('+-') 返回的结果就是:'hello' ,strip方法将字符串左右两侧的 + - 字符都 移除掉了。 |
S.swapcase() |
该方法会创建一个S的copy(拷贝),同时将copy字符串中的所有原小写字母都转为对应的大写字母, 并将所有原大写字母都转为对应的小写字母。最后将copy字符串对象作为结果返回。 |
S.title() |
该方法会创建一个S的copy(拷贝),同时将copy字符串转为标题样式的字符串。 例如:'hello world android'.title() 执行后,返回的结果就是:'Hello World Android' ,通过 title方法就得到了对应的标题样式的字符串(前面的istitle方法里,介绍过标题样式的字符串)。 |
S.translate(table [,deletechars]) |
该方法会根据table(可以由之前提到的maketrans函数生成),将字符串进行转译,如果提供了 deletechars参数,则将字符串中所有存在于deletechars里的字符都移除掉。下面会进行举例说明。 |
S.upper() |
该方法会创建一个S的copy(拷贝),同时将copy字符串里的所有小写字母都转为大写字母。 最后将copy字符串对象作为结果返回。 |
S.zfill(width) |
如果width参数小于等于S的字符个数的话,则将S直接作为结果返回。 如果width参数大于S的字符个数的话,则创建一个S的copy(拷贝),同时将copy字符串的左侧 用'0'字符填充。最后将copy字符串对象作为结果返回。 例1:'hello'.zfill(11) 执行后,返回的结果为:'000000hello' 例2:'+1123'.zfill(11) 执行后,返回的结果为:'+0000001123' ,如果原字符串的开头是'+'或'-'字符时, 会将'+'或'-'字符放置到填充符'0'的前面。 |
S.isdecimal() |
该方法与之前的isnumeric方法一样,这里的S必须是unicode字符串。 因为isdecimal方法只存在于unicode字符串对象中。 该方法用于判断字符串里的字符是否都是DECIMAL类型,要判断一个unicode字符是否是 DECIMAL类型,是由该字符对应的_PyUnicode_TypeRecord结构 (该结构位于python源码的Objects/unicodectype.c文件中)的flags字段来决定的,当flags字段存在 DECIMAL_MASK二进制位时,对应的字符就是DECIMAL类型。下面会进行举例说明。 |
static PyMethodDef string_methods[] = { /* Counterparts of the obsolete stropmodule functions; except string.maketrans(). */ {"join", (PyCFunction)string_join, METH_O, join__doc__}, {"split", (PyCFunction)string_split, METH_VARARGS, split__doc__}, {"rsplit", (PyCFunction)string_rsplit, METH_VARARGS, rsplit__doc__}, {"lower", (PyCFunction)string_lower, METH_NOARGS, lower__doc__}, {"upper", (PyCFunction)string_upper, METH_NOARGS, upper__doc__}, {"islower", (PyCFunction)string_islower, METH_NOARGS, islower__doc__}, {"isupper", (PyCFunction)string_isupper, METH_NOARGS, isupper__doc__}, {"isspace", (PyCFunction)string_isspace, METH_NOARGS, isspace__doc__}, {"isdigit", (PyCFunction)string_isdigit, METH_NOARGS, isdigit__doc__}, {"istitle", (PyCFunction)string_istitle, METH_NOARGS, istitle__doc__}, {"isalpha", (PyCFunction)string_isalpha, METH_NOARGS, isalpha__doc__}, {"isalnum", (PyCFunction)string_isalnum, METH_NOARGS, isalnum__doc__}, {"capitalize", (PyCFunction)string_capitalize, METH_NOARGS, capitalize__doc__}, {"count", (PyCFunction)string_count, METH_VARARGS, count__doc__}, {"endswith", (PyCFunction)string_endswith, METH_VARARGS, endswith__doc__}, {"partition", (PyCFunction)string_partition, METH_O, partition__doc__}, {"find", (PyCFunction)string_find, METH_VARARGS, find__doc__}, {"index", (PyCFunction)string_index, METH_VARARGS, index__doc__}, {"lstrip", (PyCFunction)string_lstrip, METH_VARARGS, lstrip__doc__}, {"replace", (PyCFunction)string_replace, METH_VARARGS, replace__doc__}, {"rfind", (PyCFunction)string_rfind, METH_VARARGS, rfind__doc__}, {"rindex", (PyCFunction)string_rindex, METH_VARARGS, rindex__doc__}, {"rstrip", (PyCFunction)string_rstrip, METH_VARARGS, rstrip__doc__}, {"rpartition", (PyCFunction)string_rpartition, METH_O, rpartition__doc__}, {"startswith", (PyCFunction)string_startswith, METH_VARARGS, startswith__doc__}, {"strip", (PyCFunction)string_strip, METH_VARARGS, strip__doc__}, {"swapcase", (PyCFunction)string_swapcase, METH_NOARGS, swapcase__doc__}, {"translate", (PyCFunction)string_translate, METH_VARARGS, translate__doc__}, {"title", (PyCFunction)string_title, METH_NOARGS, title__doc__}, {"ljust", (PyCFunction)string_ljust, METH_VARARGS, ljust__doc__}, {"rjust", (PyCFunction)string_rjust, METH_VARARGS, rjust__doc__}, {"center", (PyCFunction)string_center, METH_VARARGS, center__doc__}, {"zfill", (PyCFunction)string_zfill, METH_VARARGS, zfill__doc__}, {"format", (PyCFunction) do_string_format, METH_VARARGS | METH_KEYWORDS, format__doc__}, {"__format__", (PyCFunction) string__format__, METH_VARARGS, p_format__doc__}, {"_formatter_field_name_split", (PyCFunction) formatter_field_name_split, METH_NOARGS}, {"_formatter_parser", (PyCFunction) formatter_parser, METH_NOARGS}, {"encode", (PyCFunction)string_encode, METH_VARARGS | METH_KEYWORDS, encode__doc__}, {"decode", (PyCFunction)string_decode, METH_VARARGS | METH_KEYWORDS, decode__doc__}, {"expandtabs", (PyCFunction)string_expandtabs, METH_VARARGS, expandtabs__doc__}, {"splitlines", (PyCFunction)string_splitlines, METH_VARARGS, splitlines__doc__}, {"__sizeof__", (PyCFunction)string_sizeof, METH_NOARGS, sizeof__doc__}, {"__getnewargs__", (PyCFunction)string_getnewargs, METH_NOARGS}, {NULL, NULL} /* sentinel */ }; |
static PyMethodDef unicode_methods[] = { {"encode", (PyCFunction) unicode_encode, METH_VARARGS | METH_KEYWORDS, encode__doc__}, {"replace", (PyCFunction) unicode_replace, METH_VARARGS, replace__doc__}, {"split", (PyCFunction) unicode_split, METH_VARARGS, split__doc__}, {"rsplit", (PyCFunction) unicode_rsplit, METH_VARARGS, rsplit__doc__}, {"join", (PyCFunction) unicode_join, METH_O, join__doc__}, {"capitalize", (PyCFunction) unicode_capitalize, METH_NOARGS, capitalize__doc__}, {"title", (PyCFunction) unicode_title, METH_NOARGS, title__doc__}, {"center", (PyCFunction) unicode_center, METH_VARARGS, center__doc__}, {"count", (PyCFunction) unicode_count, METH_VARARGS, count__doc__}, {"expandtabs", (PyCFunction) unicode_expandtabs, METH_VARARGS, expandtabs__doc__}, {"find", (PyCFunction) unicode_find, METH_VARARGS, find__doc__}, {"partition", (PyCFunction) unicode_partition, METH_O, partition__doc__}, {"index", (PyCFunction) unicode_index, METH_VARARGS, index__doc__}, {"ljust", (PyCFunction) unicode_ljust, METH_VARARGS, ljust__doc__}, {"lower", (PyCFunction) unicode_lower, METH_NOARGS, lower__doc__}, {"lstrip", (PyCFunction) unicode_lstrip, METH_VARARGS, lstrip__doc__}, {"decode", (PyCFunction) unicode_decode, METH_VARARGS | METH_KEYWORDS, decode__doc__}, /* {"maketrans", (PyCFunction) unicode_maketrans, METH_VARARGS, maketrans__doc__}, */ {"rfind", (PyCFunction) unicode_rfind, METH_VARARGS, rfind__doc__}, {"rindex", (PyCFunction) unicode_rindex, METH_VARARGS, rindex__doc__}, {"rjust", (PyCFunction) unicode_rjust, METH_VARARGS, rjust__doc__}, {"rstrip", (PyCFunction) unicode_rstrip, METH_VARARGS, rstrip__doc__}, {"rpartition", (PyCFunction) unicode_rpartition, METH_O, rpartition__doc__}, {"splitlines", (PyCFunction) unicode_splitlines, METH_VARARGS, splitlines__doc__}, {"strip", (PyCFunction) unicode_strip, METH_VARARGS, strip__doc__}, {"swapcase", (PyCFunction) unicode_swapcase, METH_NOARGS, swapcase__doc__}, {"translate", (PyCFunction) unicode_translate, METH_O, translate__doc__}, {"upper", (PyCFunction) unicode_upper, METH_NOARGS, upper__doc__}, {"startswith", (PyCFunction) unicode_startswith, METH_VARARGS, startswith__doc__}, {"endswith", (PyCFunction) unicode_endswith, METH_VARARGS, endswith__doc__}, {"islower", (PyCFunction) unicode_islower, METH_NOARGS, islower__doc__}, {"isupper", (PyCFunction) unicode_isupper, METH_NOARGS, isupper__doc__}, {"istitle", (PyCFunction) unicode_istitle, METH_NOARGS, istitle__doc__}, {"isspace", (PyCFunction) unicode_isspace, METH_NOARGS, isspace__doc__}, {"isdecimal", (PyCFunction) unicode_isdecimal, METH_NOARGS, isdecimal__doc__}, {"isdigit", (PyCFunction) unicode_isdigit, METH_NOARGS, isdigit__doc__}, {"isnumeric", (PyCFunction) unicode_isnumeric, METH_NOARGS, isnumeric__doc__}, {"isalpha", (PyCFunction) unicode_isalpha, METH_NOARGS, isalpha__doc__}, {"isalnum", (PyCFunction) unicode_isalnum, METH_NOARGS, isalnum__doc__}, {"zfill", (PyCFunction) unicode_zfill, METH_VARARGS, zfill__doc__}, {"format", (PyCFunction) do_string_format, METH_VARARGS | METH_KEYWORDS, format__doc__}, {"__format__", (PyCFunction) unicode__format__, METH_VARARGS, p_format__doc__}, {"_formatter_field_name_split", (PyCFunction) formatter_field_name_split, METH_NOARGS}, {"_formatter_parser", (PyCFunction) formatter_parser, METH_NOARGS}, {"__sizeof__", (PyCFunction) unicode__sizeof__, METH_NOARGS, sizeof__doc__}, #if 0 {"capwords", (PyCFunction) unicode_capwords, METH_NOARGS, capwords__doc__}, #endif #if 0 /* This one is just used for debugging the implementation. */ {"freelistsize", (PyCFunction) free_listsize, METH_NOARGS}, #endif {"__getnewargs__", (PyCFunction)unicode_getnewargs, METH_NOARGS}, {NULL, NULL} }; |
PyDoc_STRVAR(capitalize__doc__, "S.capitalize() -> string\n\ \n\ Return a copy of the string S with only its first character\n\ capitalized."); static PyObject * string_capitalize(PyStringObject *self) { char *s = PyString_AS_STRING(self), *s_new; Py_ssize_t i, n = PyString_GET_SIZE(self); PyObject *newobj; // 通过PyString_FromStringAndSize创建一个相同尺寸的字符串对象, // 转换后的结果将存储在该字符串对象里。 newobj = PyString_FromStringAndSize(NULL, n); if (newobj == NULL) return NULL; s_new = PyString_AsString(newobj); if (0 < n) { int c = Py_CHARMASK(*s++); // 如果第一个字符是小写字母, // 则转成大写字母。 if (islower(c)) *s_new = toupper(c); else *s_new = c; s_new++; } for (i = 1; i < n; i++) { int c = Py_CHARMASK(*s++); // 其余的字符如果是大写字母, // 则都转为小写字母。 if (isupper(c)) *s_new = tolower(c); else *s_new = c; s_new++; } return newobj; } |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> 'hello WoRld'.capitalize() 'Hello world' >>> help(''.capitalize) Help on built-in function capitalize: capitalize(...) S.capitalize() -> string Return a copy of the string S with only its first character capitalized. lines 1-7/7 (END) >>> quit() [email protected]:~$ |
Py_LOCAL_INLINE(PyObject *) pad(PyStringObject *self, Py_ssize_t left, Py_ssize_t right, char fill) { PyObject *u; if (left < 0) left = 0; if (right < 0) right = 0; if (left == 0 && right == 0 && PyString_CheckExact(self)) { Py_INCREF(self); return (PyObject *)self; } // 根据left(左侧需要填充的字符数),right(右侧需要填充的字符数), // 以及self本身的字符个数,创建一个新的字符串对象。 u = PyString_FromStringAndSize(NULL, left + PyString_GET_SIZE(self) + right); if (u) { // 如果左侧需要填充字符的话,则用memset函数来对 // 新字符串对象的左侧进行填充。 if (left) memset(PyString_AS_STRING(u), fill, left); // 通过Py_MEMCPY拷贝函数将self中原始的字符串数据 // 拷贝到新的字符串对象里。 Py_MEMCPY(PyString_AS_STRING(u) + left, PyString_AS_STRING(self), PyString_GET_SIZE(self)); // 如果需要对右侧进行填充的话,则用memset函数 // 对新字符串的右侧进行填充。 if (right) memset(PyString_AS_STRING(u) + left + PyString_GET_SIZE(self), fill, right); } return u; } .................................................... static PyObject * string_center(PyStringObject *self, PyObject *args) { Py_ssize_t marg, left; Py_ssize_t width; // 默认的填充字符为空格符 char fillchar = ' '; // 获取Python脚本提供的width和fillchar参数(其中fillchar为可选参数) // PyArg_ParseTuple的第二个参数中,竖线左侧的为必须提供的参数, // 这里为n,也就是必须提供一个int(整数参数)来作为width , // 竖线右侧的为可选参数,此处为c ,表示第二个参数是可选的char(字符参数,字符就是长度为1的字符串) // 来作为fillchar(填充字符) if (!PyArg_ParseTuple(args, "n|c:center", &width, &fillchar)) return NULL; // 当width小于等于self(当前方法所对应的字符串对象) // 的字符个数时,直接将self返回。 if (PyString_GET_SIZE(self) >= width && PyString_CheckExact(self)) { Py_INCREF(self); return (PyObject*) self; } marg = width - PyString_GET_SIZE(self); left = marg / 2 + (marg & width & 1); // pad函数会创建一个self的copy字符串, // left参数表示需要在copy字符串左侧填充多少个fillchar , // marg - left参数表示需要在copy字符串右侧填充多少个fillchar , // 通过左右填充,让copy字符串居中对齐,最后将copy字符串返回。 return pad(self, left, marg - left, fillchar); } |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> 'hello'.center(11) ' hello ' >>> 'hello'.center(11,'-') '---hello---' >>> 'hello'.center(11,'--') Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: must be char, not str >>> quit() [email protected]:~$ |
static PyObject * string_count(PyStringObject *self, PyObject *args) { ............................................... Py_ssize_t start = 0, end = PY_SSIZE_T_MAX; // 通过stringlib_parse_args_finds函数解析出 // 脚本提供的sub,start和end三个参数(start与end是可选的参数) // stringlib_parse_args_finds函数定义于Objects/stringlib/find.h文件中。 if (!stringlib_parse_args_finds("count", args, &sub_obj, &start, &end)) return NULL; if (PyString_Check(sub_obj)) { sub = PyString_AS_STRING(sub_obj); sub_len = PyString_GET_SIZE(sub_obj); } ............................................... // 对start,end进行调整,比如没提供end时, // end就会是默认的PY_SSIZE_T_MAX,这是一个很大的数 // ADJUST_INDICES宏就会将end调整为self本身的字符个数。 // ADJUST_INDICES宏也定义在Objects/stringlib/find.h文件中。 ADJUST_INDICES(start, end, PyString_GET_SIZE(self)); // 通过stringlib_count在以str + start为起点的, // 以end - start为长度的字符串中,统计sub子字符串的个数。 // stringlib_count函数定义在Objects/stringlib/count.h文件里。 // str为self字符串对象的字符串指针 return PyInt_FromSsize_t( stringlib_count(str + start, end - start, sub, sub_len, PY_SSIZE_T_MAX) ); } |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> 'hello hello hello'.count('he') 3 >>> 'hello hello hello'.count('he', 2) 2 >>> 'hello hello hello'.count('he', 2, 8) 1 >>> 'hello hello hello'.count('he', -5, -3) 1 >>> quit() [email protected]:~$ |
/* helper macro to fixup start/end slice values */ #define ADJUST_INDICES(start, end, len) \ if (end > len) \ end = len; \ else if (end < 0) { \ end += len; \ if (end < 0) \ end = 0; \ } \ if (start < 0) { \ start += len; \ if (start < 0) \ start = 0; \ } |
[email protected]:~$ ls /usr/local/lib/python2.7/encodings/ ..................................................... ascii.py cp875.py koi8_u.py ascii.pyc cp875.pyc koi8_u.pyc ascii.pyo cp875.pyo koi8_u.pyo base64_codec.py cp932.py latin_1.py base64_codec.pyc cp932.pyc latin_1.pyc ..................................................... cp1255.py __init__.py ptcp154.py cp1255.pyc __init__.pyc ptcp154.pyc cp1255.pyo __init__.pyo ptcp154.pyo ..................................................... [email protected]:~$ |
.................................................... import codecs from encodings import aliases import __builtin__ _cache = {} .................................................... def search_function(encoding): ................................................. # Register the search_function in the Python codec registry codecs.register(search_function) |
................................................... import codecs, base64 ### Codec APIs def base64_encode(input,errors='strict'): ................................................... assert errors == 'strict' output = base64.encodestring(input) return (output, len(input)) def base64_decode(input,errors='strict'): ................................................... assert errors == 'strict' output = base64.decodestring(input) return (output, len(input)) ................................................... def getregentry(): return codecs.CodecInfo( name='base64', encode=base64_encode, decode=base64_decode, incrementalencoder=IncrementalEncoder, incrementaldecoder=IncrementalDecoder, streamwriter=StreamWriter, streamreader=StreamReader, ) |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> 'hello'.encode('base64') 'aGVsbG8=\n' >>> 'aGVsbG8=\n'.decode('base64') 'hello' >>> 'hello'.encode('zlib') 'x\x9c\xcbH\xcd\xc9\xc9\x07\x00\x06,\x02\x15' >>> 'x\x9c\xcbH\xcd\xc9\xc9\x07\x00\x06,\x02\x15'.decode('zlib') 'hello' >>> 'x\x9c\xcbH\xcd\xc9\xc9\x07\x00\x06,\x02\x15'.decode('zip') 'hello' >>> quit() [email protected]:~$ |
................................................... aliases = { ................................................. # base64_codec codec 'base64' : 'base64_codec', 'base_64' : 'base64_codec', ................................................. # utf_8 codec 'u8' : 'utf_8', 'utf' : 'utf_8', 'utf8' : 'utf_8', 'utf8_ucs2' : 'utf_8', 'utf8_ucs4' : 'utf_8', # uu_codec codec 'uu' : 'uu_codec', # zlib_codec codec 'zip' : 'zlib_codec', 'zlib' : 'zlib_codec', } |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> 'hello'.encode('base64') 'aGVsbG8=\n' >>> 'hello'.encode('base_64') 'aGVsbG8=\n' >>> u'hello'.encode('u8') 'hello' >>> u'hello'.encode('utf') 'hello' >>> u'hello'.encode('utf8') 'hello' >>> u'hello'.encode('utf8_ucs2') 'hello' >>> u'hello'.encode('utf8_ucs4') 'hello' >>> 'hello'.encode('uu') 'begin 666 <data>\n%:&5L;&\\ \n \nend\n' >>> 'begin 666 <data>\n%:&5L;&\\ \n \nend\n'.decode('uu') 'hello' >>> 'hello'.encode('zip') 'x\x9c\xcbH\xcd\xc9\xc9\x07\x00\x06,\x02\x15' >>> 'hello'.encode('zlib') 'x\x9c\xcbH\xcd\xc9\xc9\x07\x00\x06,\x02\x15' >>> quit() [email protected]:~$ |
Py_LOCAL(int) _string_tailmatch(PyStringObject *self, PyObject *substr, Py_ssize_t start, Py_ssize_t end, int direction) { Py_ssize_t len = PyString_GET_SIZE(self); Py_ssize_t slen; const char* sub; const char* str; // 获取需要进行匹配的substr字符串对象的 // 数据指针和数据长度。 if (PyString_Check(substr)) { sub = PyString_AS_STRING(substr); slen = PyString_GET_SIZE(substr); } ................................................ // 获取self主体字符串对象的数据指针。 str = PyString_AS_STRING(self); // 通过ADJUST_INDICES宏对start,end的值进行调整, // 让start起始偏移值与end结束偏移值位于有效的范围内。 ADJUST_INDICES(start, end, len); // 当该函数的最后一个参数direction小于0时, // (主要用于startswith方法) // start起始位置就不做调整,最后的memcmp函数就会在 // 主体字符串的开头对substr进行匹配判断。 if (direction < 0) { /* startswith */ if (start+slen > len) return 0; } else { /* endswith */ if (end-start < slen || start > len) return 0; // 当direction大于等于0时, // (主要用于endswith方法) // 就根据substr字符串对象的数据长度, // 将start调整到主体字符串的结尾位置处, // 此时start与end之间的字符个数刚好就是 // slen即substr字符串对象的数据长度。 // 最后的memcmp函数就会在新的start位置处, // 也就是主体字符串的结尾, // 对substr进行匹配判断。 if (end-slen > start) start = end - slen; } if (end-start >= slen) return ! memcmp(str+start, sub, slen); return 0; } PyDoc_STRVAR(startswith__doc__, "S.startswith(prefix[, start[, end]]) -> bool\n\ \n\ Return True if S starts with the specified prefix, False otherwise.\n\ With optional start, test S beginning at that position.\n\ With optional end, stop comparing S at that position.\n\ prefix can also be a tuple of strings to try."); static PyObject * string_startswith(PyStringObject *self, PyObject *args) { Py_ssize_t start = 0; Py_ssize_t end = PY_SSIZE_T_MAX; PyObject *subobj; int result; // 从脚本中获取suffix,start与end三个参数, // 其中suffix参数会被设置到subobj对象里, // start与end参数为可选参数。 if (!stringlib_parse_args_finds("startswith", args, &subobj, &start, &end)) return NULL; // 第一个subobj参数可以是tuple元组,如果是元组, // 则将元组里的每个字符串依次提取出来, // 并通过_string_tailmatch函数来判断self[start:end]字符串 // 是否是以元组里的这些字符串开头的。 // 只要元组中有一个匹配,就返回True, // _string_tailmatch函数的最后一个参数为-1, // 当该参数小于0时,就会对主体字符串的开头位置 // 进行匹配判断,实际的匹配方法,可以参考 // 上面的_string_tailmatch函数的代码。 if (PyTuple_Check(subobj)) { Py_ssize_t i; for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) { result = _string_tailmatch(self, PyTuple_GET_ITEM(subobj, i), start, end, -1); if (result == -1) return NULL; else if (result) { Py_RETURN_TRUE; } } Py_RETURN_FALSE; } // 如果subobj不是元组,则直接通过 // _string_tailmatch函数来判断self[start:end]字符串 // 是否是以subobj字符串开头的。 result = _string_tailmatch(self, subobj, start, end, -1); if (result == -1) { if (PyErr_ExceptionMatches(PyExc_TypeError)) PyErr_Format(PyExc_TypeError, "startswith first arg must be str, " "unicode, or tuple, not %s", Py_TYPE(subobj)->tp_name); return NULL; } else return PyBool_FromLong(result); } PyDoc_STRVAR(endswith__doc__, "S.endswith(suffix[, start[, end]]) -> bool\n\ \n\ Return True if S ends with the specified suffix, False otherwise.\n\ With optional start, test S beginning at that position.\n\ With optional end, stop comparing S at that position.\n\ suffix can also be a tuple of strings to try."); static PyObject * string_endswith(PyStringObject *self, PyObject *args) { Py_ssize_t start = 0; Py_ssize_t end = PY_SSIZE_T_MAX; PyObject *subobj; int result; // 从脚本中获取suffix,start与end三个参数, // 其中suffix参数会被设置到subobj对象里, // start与end参数为可选参数。 if (!stringlib_parse_args_finds("endswith", args, &subobj, &start, &end)) return NULL; // 第一个subobj参数可以是tuple元组,如果是元组, // 则将元组里的每个字符串依次提取出来, // 并通过_string_tailmatch函数来判断self[start:end]字符串 // 是否是以元组里的这些字符串结尾的。 // 只要元组中有一个匹配,就返回True, // _string_tailmatch函数的最后一个参数为+1, // 当该参数大于等于0时,就会对主体字符串的结尾位置 // 进行匹配判断,实际的匹配方法,可以参考 // 上面的_string_tailmatch函数的代码。 if (PyTuple_Check(subobj)) { Py_ssize_t i; for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) { result = _string_tailmatch(self, PyTuple_GET_ITEM(subobj, i), start, end, +1); if (result == -1) return NULL; else if (result) { Py_RETURN_TRUE; } } Py_RETURN_FALSE; } // 如果subobj不是元组,则直接通过 // _string_tailmatch函数来判断self[start:end]字符串 // 是否是以subobj字符串结尾的。 result = _string_tailmatch(self, subobj, start, end, +1); if (result == -1) { if (PyErr_ExceptionMatches(PyExc_TypeError)) PyErr_Format(PyExc_TypeError, "endswith first arg must be str, " "unicode, or tuple, not %s", Py_TYPE(subobj)->tp_name); return NULL; } else return PyBool_FromLong(result); } |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> 'hello'.startswith(('he', 'wor')) True >>> 'world'.startswith(('he', 'wor')) True >>> 'hello world'.startswith('wor', 6) True >>> 'hello world'[6:].startswith('wor') True >>> help(''.startswith) Help on built-in function startswith: startswith(...) S.startswith(prefix[, start[, end]]) -> bool Return True if S starts with the specified prefix, False otherwise. With optional start, test S beginning at that position. With optional end, stop comparing S at that position. prefix can also be a tuple of strings to try. lines 1-9/9 (END) >>> 'hello'.endswith(('rld', 'llo')) True >>> 'world'.endswith(('rld', 'llo')) True >>> 'hello'.endswith(('rld', 'll')) False >>> 'hello'.endswith('llo') True >>> 'hello'.endswith('rld') False >>> 'hello'.endswith('ll', 1, 4) True >>> 'hello'[1:4].endswith('ll') True >>> help(''.endswith) Help on built-in function endswith: endswith(...) S.endswith(suffix[, start[, end]]) -> bool Return True if S ends with the specified suffix, False otherwise. With optional start, test S beginning at that position. With optional end, stop comparing S at that position. suffix can also be a tuple of strings to try. lines 1-9/9 (END) >>> quit() [email protected]:~$ |
PyDoc_STRVAR(expandtabs__doc__, "S.expandtabs([tabsize]) -> string\n\ \n\ Return a copy of S where all tab characters are expanded using spaces.\n\ If tabsize is not given, a tab size of 8 characters is assumed."); static PyObject* string_expandtabs(PyStringObject *self, PyObject *args) { ................................................. // 默认的tabsize值为8,即默认情况下, // 每8个字符为一个tab边界。 int tabsize = 8; // 从脚本中获取expandtabs方法的tabsize参数。 // 该参数是可选的,因此,如果脚本中没有提供该参数的话, // 就保持默认值,即上面设置过的8 。 if (!PyArg_ParseTuple(args, "|i:expandtabs", &tabsize)) return NULL; /* First pass: determine size of output string */ ................................................. /* Second pass: create output string and fill it */ ................................................. for (p = PyString_AS_STRING(self); p < e; p++) { // 将\t即tab制表符,根据tabsize, // 替换为特定数量的空格符。 // 替换出来的空格符的数量不一定等于tabsize, // 它只会将\t后面的字符推到下一个tab边界去。 // 例如: 'hello\t world',由于开头已经有了hello这5个字符了, // 因此\t就只会被替换为3个空格符。这里假设'hello'刚好位于 // tab边界的起始位置处。 if (*p == '\t') { if (tabsize > 0) { i = tabsize - (j % tabsize); j += i; while (i--) { if (q >= qe) goto overflow2; *q++ = ' '; } } } ................................................. } ................................................. } |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> 'hello\t world'.expandtabs() 'hello world' >>> 'hello\t world'.expandtabs(4) 'hello world' >>> 'hello\t world'.expandtabs(8) 'hello world' >>> 'hello\t world'.expandtabs(16) 'hello world' >>> quit() [email protected]:~$ |
Py_LOCAL_INLINE(Py_ssize_t) string_find_internal(PyStringObject *self, PyObject *args, int dir) { ................................................ // find,rfind,index及rindex这4个方法都有3个参数, // 第一个参数为需要查找的子字符串对象, // 第二个与第三个是可选的参数,表示需要进行查找的起始与结束位置。 if (!stringlib_parse_args_finds("find/rfind/index/rindex", args, &subobj, &start, &end)) return -2; if (PyString_Check(subobj)) { sub = PyString_AS_STRING(subobj); sub_len = PyString_GET_SIZE(subobj); } ................................................ // 对于find和index方法,会通过stringlib_find_slice函数 // 从start往end方向查找sub子字符串。 // stringlib_find_slice函数定义在Objects/stringlib/find.h文件中 if (dir > 0) return stringlib_find_slice( PyString_AS_STRING(self), PyString_GET_SIZE(self), sub, sub_len, start, end); // 对于rfind和rindex方法,则会通过stringlib_rfind_slice函数 // 从end往start方向查找sub子字符串。 // stringlib_rfind_slice函数也定义在Objects/stringlib/find.h文件中 else return stringlib_rfind_slice( PyString_AS_STRING(self), PyString_GET_SIZE(self), sub, sub_len, start, end); } .................................................... static PyObject * string_find(PyStringObject *self, PyObject *args) { Py_ssize_t result = string_find_internal(self, args, +1); if (result == -2) return NULL; return PyInt_FromSsize_t(result); } .................................................... static PyObject * string_index(PyStringObject *self, PyObject *args) { Py_ssize_t result = string_find_internal(self, args, +1); if (result == -2) return NULL; // 当index方法查找不到sub子字符串时, // 会抛出ValueError异常,而不会像find方法 // 那样返回-1 。 if (result == -1) { PyErr_SetString(PyExc_ValueError, "substring not found"); return NULL; } return PyInt_FromSsize_t(result); } .................................................... static PyObject * string_rfind(PyStringObject *self, PyObject *args) { Py_ssize_t result = string_find_internal(self, args, -1); if (result == -2) return NULL; return PyInt_FromSsize_t(result); } .................................................... static PyObject * string_rindex(PyStringObject *self, PyObject *args) { Py_ssize_t result = string_find_internal(self, args, -1); if (result == -2) return NULL; // 当rindex方法查找不到sub子字符串时, // 会抛出ValueError异常,而不会像rfind方法 // 那样返回-1 。 if (result == -1) { PyErr_SetString(PyExc_ValueError, "substring not found"); return NULL; } return PyInt_FromSsize_t(result); } |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> 'hello hello'.find('he') 0 >>> 'hello hello'.rfind('he') 6 >>> 'hello hello'.index('he') 0 >>> 'hello hello'.rindex('he') 6 >>> 'hello hello'.find('hex') -1 >>> 'hello hello'.rfind('hex') -1 >>> 'hello hello'.index('hex') Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: substring not found >>> 'hello hello'.rindex('hex') Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: substring not found >>> 'hello hello'.find('he', 2) 6 >>> 'hello hello'.rfind('he', 0, 5) 0 >>> 'hello hello'[2:].find('he') 4 >>> 'hello hello'[0:5].rfind('he') 0 >>> quit() [email protected]:~$ |
static PyObject* string_isalpha(PyStringObject *self) { register const unsigned char *p = (unsigned char *) PyString_AS_STRING(self); register const unsigned char *e; // 当字符串中只包含一个字符, // 且该字符为字母时,就返回True // PyBool_FromLong定义在Objects/boolobject.c文件中, // 当PyBool_FromLong的参数不为0时,就返回True对象。 // 当PyBool_FromLong的参数为0时,就返回False对象。 /* Shortcut for single character strings */ if (PyString_GET_SIZE(self) == 1 && isalpha(*p)) return PyBool_FromLong(1); // 对于空字符串(字符个数为0的字符串), // 直接返回False /* Special case for empty strings */ if (PyString_GET_SIZE(self) == 0) return PyBool_FromLong(0); e = p + PyString_GET_SIZE(self); // 循环通过libc.so(C标准库)里的 // isalpha函数来判断字符串中的字符是否是字母, // 如果所有的字符都是字母时,就返回True, // 否则返回False for (; p < e; p++) { if (!isalpha(*p)) return PyBool_FromLong(0); } return PyBool_FromLong(1); } .................................................... static PyObject* string_isalnum(PyStringObject *self) { register const unsigned char *p = (unsigned char *) PyString_AS_STRING(self); register const unsigned char *e; // 当字符串中只包含一个字符, // 且该字符为字母或数字时,就返回True /* Shortcut for single character strings */ if (PyString_GET_SIZE(self) == 1 && isalnum(*p)) return PyBool_FromLong(1); // 对于空字符串直接返回False /* Special case for empty strings */ if (PyString_GET_SIZE(self) == 0) return PyBool_FromLong(0); e = p + PyString_GET_SIZE(self); // 循环通过libc.so(C标准库)里的 // isalnum函数来判断字符串中的字符是否是字母或数字, // 如果所有的字符都是字母或数字时,就返回True, // 否则返回False for (; p < e; p++) { if (!isalnum(*p)) return PyBool_FromLong(0); } return PyBool_FromLong(1); } .................................................... static PyObject* string_isdigit(PyStringObject *self) { register const unsigned char *p = (unsigned char *) PyString_AS_STRING(self); register const unsigned char *e; // 当字符串中只包含一个字符, // 且该字符为0到9的数字时,就返回True /* Shortcut for single character strings */ if (PyString_GET_SIZE(self) == 1 && isdigit(*p)) return PyBool_FromLong(1); // 对于空字符串直接返回False /* Special case for empty strings */ if (PyString_GET_SIZE(self) == 0) return PyBool_FromLong(0); e = p + PyString_GET_SIZE(self); // 循环通过libc.so(C标准库)里的 // isdigit函数来判断字符串中的字符是否是数字, // 如果所有的字符都是数字时,就返回True, // 否则返回False for (; p < e; p++) { if (!isdigit(*p)) return PyBool_FromLong(0); } return PyBool_FromLong(1); } |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> 'hello'.isalpha() True >>> 'hello123'.isalpha() False >>> '0123456'.isalpha() False >>> ''.isalpha() False >>> 'hello'.isalnum() True >>> 'hello12345'.isalnum() True >>> '0123456'.isalnum() True >>> '0123456'.isdigit() True >>> '0123456hello'.isdigit() False >>> quit() [email protected]:~$ |
static PyObject* string_islower(PyStringObject *self) { register const unsigned char *p = (unsigned char *) PyString_AS_STRING(self); register const unsigned char *e; int cased; // 当字符串中只有一个字符时, // 如果这个字符为小写字母,就返回True, // 否则返回False /* Shortcut for single character strings */ if (PyString_GET_SIZE(self) == 1) return PyBool_FromLong(islower(*p) != 0); // 空字符串直接返回False /* Special case for empty strings */ if (PyString_GET_SIZE(self) == 0) return PyBool_FromLong(0); e = p + PyString_GET_SIZE(self); // cased变量是用于判断字符串中是否存在小写字母的, // 当字符串中至少存在一个小写字母时, // cased变量就会被设置为1, // 因此,islower方法并不要求所有的字符都是小写字母, // 它只要求字符串中至少有一个小写字母就可以了。 cased = 0; for (; p < e; p++) { // 如果字符串中存在大写字母的话, // 则直接返回False if (isupper(*p)) return PyBool_FromLong(0); // 只要字符串中存在一个小写字母, // cased的值就会变为1 else if (!cased && islower(*p)) cased = 1; } // 当cased为1时,PyBool_FromLong函数会返回True对象 // 当cased为0时,PyBool_FromLong函数会返回False对象 return PyBool_FromLong(cased); } .................................................... static PyObject* string_isupper(PyStringObject *self) { register const unsigned char *p = (unsigned char *) PyString_AS_STRING(self); register const unsigned char *e; int cased; // 当字符串中只有一个字符时, // 如果这个字符为大写字母,就返回True, // 否则返回False /* Shortcut for single character strings */ if (PyString_GET_SIZE(self) == 1) return PyBool_FromLong(isupper(*p) != 0); // 空字符串直接返回False /* Special case for empty strings */ if (PyString_GET_SIZE(self) == 0) return PyBool_FromLong(0); e = p + PyString_GET_SIZE(self); // cased变量是用于判断字符串中是否存在大写字母的, // 当字符串中至少存在一个大写字母时, // cased变量就会被设置为1, // 因此,isupper方法并不要求所有的字符都是大写字母, // 它只要求字符串中至少有一个大写字母就可以了。 cased = 0; for (; p < e; p++) { // 如果字符串中存在小写字母的话, // 则直接返回False if (islower(*p)) return PyBool_FromLong(0); // 只要字符串中存在一个大写字母, // cased的值就会变为1 else if (!cased && isupper(*p)) cased = 1; } // 当cased为1时,PyBool_FromLong函数会返回True对象 // 当cased为0时,PyBool_FromLong函数会返回False对象 return PyBool_FromLong(cased); } |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> 'hello world!!!~~(^_^)~~'.islower() True >>> 'HELLO WORLD!!!~~(^_^)~~'.isupper() True >>> 'hello World'.islower() False >>> 'hello World'.isupper() False >>> '!!!~~(^_^)~~'.islower() False >>> '!!!~~(^_^)~~'.isupper() False >>> quit() [email protected]:~$ |
.................................................... #define ALPHA_MASK 0x01 #define DECIMAL_MASK 0x02 #define DIGIT_MASK 0x04 #define LOWER_MASK 0x08 #define LINEBREAK_MASK 0x10 #define SPACE_MASK 0x20 #define TITLE_MASK 0x40 #define UPPER_MASK 0x80 #define NODELTA_MASK 0x100 #define NUMERIC_MASK 0x200 typedef struct { const Py_UNICODE upper; const Py_UNICODE lower; const Py_UNICODE title; const unsigned char decimal; const unsigned char digit; const unsigned short flags; } _PyUnicode_TypeRecord; #include "unicodetype_db.h" .................................................... |
/* this file was generated by Tools/unicode/makeunicodedata.py 2.6 */ /* a list of unique character type descriptors */ const _PyUnicode_TypeRecord _PyUnicode_TypeRecords[] = { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 32}, {0, 0, 0, 0, 0, 48}, {0, 0, 0, 0, 0, 518}, {0, 0, 0, 1, 1, 518}, {0, 0, 0, 2, 2, 518}, {0, 0, 0, 3, 3, 518}, {0, 0, 0, 4, 4, 518}, {0, 0, 0, 5, 5, 518}, {0, 0, 0, 6, 6, 518}, {0, 0, 0, 7, 7, 518}, {0, 0, 0, 8, 8, 518}, {0, 0, 0, 9, 9, 518}, ................................................ }; .................................................... |
static PyObject* unicode_isdecimal(PyUnicodeObject *self) { register const Py_UNICODE *p = PyUnicode_AS_UNICODE(self); register const Py_UNICODE *e; // 当unicode字符串中只包含一个字符时, // 如果这个字符是DECIMAL类型,那么就返回True /* Shortcut for single character strings */ if (PyUnicode_GET_SIZE(self) == 1 && Py_UNICODE_ISDECIMAL(*p)) return PyBool_FromLong(1); // 空字符串直接返回False /* Special case for empty strings */ if (PyUnicode_GET_SIZE(self) == 0) return PyBool_FromLong(0); e = p + PyUnicode_GET_SIZE(self); // 如果字符串里的字符都是DECIMAL类型, // 就返回True,否则返回False for (; p < e; p++) { if (!Py_UNICODE_ISDECIMAL(*p)) return PyBool_FromLong(0); } return PyBool_FromLong(1); } .................................................... static PyObject* unicode_isnumeric(PyUnicodeObject *self) { register const Py_UNICODE *p = PyUnicode_AS_UNICODE(self); register const Py_UNICODE *e; // 当unicode字符串中只包含一个字符时, // 如果这个字符是NUMERIC类型,那么就返回True /* Shortcut for single character strings */ if (PyUnicode_GET_SIZE(self) == 1 && Py_UNICODE_ISNUMERIC(*p)) return PyBool_FromLong(1); // 空字符串直接返回False /* Special case for empty strings */ if (PyUnicode_GET_SIZE(self) == 0) return PyBool_FromLong(0); e = p + PyUnicode_GET_SIZE(self); // 如果字符串里的字符都是NUMERIC类型, // 就返回True,否则返回False for (; p < e; p++) { if (!Py_UNICODE_ISNUMERIC(*p)) return PyBool_FromLong(0); } return PyBool_FromLong(1); } |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> u'0123456789'.isnumeric() True >>> u'零一二三四五六七八九'.isnumeric() True >>> u'0123456789'.isdecimal() True >>> u'零一二三四五六七八九'.isdecimal() False >>> for i in range(65535): ... if(unichr(i).isnumeric()): ... print '%#x' % i ... print u'%c' % unichr(i) ... 0x30 0 0x31 1 0x32 2 0x33 3 0x34 4 0x35 5 .................... // 省略掉N行输出信息 >>> for i in range(65535): ... if(unichr(i).isdecimal()): ... print '%#x' % i ... print u'%c' % unichr(i) ... 0x30 0 0x31 1 0x32 2 0x33 3 0x34 4 0x35 5 .................... // 省略掉N行输出信息 >>> quit() [email protected]:~$ |
static PyObject* string_isspace(PyStringObject *self) { register const unsigned char *p = (unsigned char *) PyString_AS_STRING(self); register const unsigned char *e; // 当字符串中只包含一个字符, // 且该字符为空白字符时,就返回True // 空白符可以是空格符,\f(换页符), // \n(换行符),\r(回车符),\t(水平制表符), // 以及\v(垂直制表符) /* Shortcut for single character strings */ if (PyString_GET_SIZE(self) == 1 && isspace(*p)) return PyBool_FromLong(1); // 对于空字符串直接返回False /* Special case for empty strings */ if (PyString_GET_SIZE(self) == 0) return PyBool_FromLong(0); e = p + PyString_GET_SIZE(self); // 循环通过libc.so(C标准库)里的 // isspace函数来判断字符串中的字符是否是空白字符, // 如果所有的字符都是空白字符时,就返回True, // 否则返回False for (; p < e; p++) { if (!isspace(*p)) return PyBool_FromLong(0); } return PyBool_FromLong(1); } |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> ' \r\n\v\f\t'.isspace() True >>> 'hello'.isspace() False >>> quit() [email protected]:~$ |
static PyObject* string_istitle(PyStringObject *self, PyObject *uncased) { register const unsigned char *p = (unsigned char *) PyString_AS_STRING(self); register const unsigned char *e; int cased, previous_is_cased; // 当字符串中只包含一个字符, // 且该字符为大写字母时,就返回True /* Shortcut for single character strings */ if (PyString_GET_SIZE(self) == 1) return PyBool_FromLong(isupper(*p) != 0); // 对于空字符串,直接返回False /* Special case for empty strings */ if (PyString_GET_SIZE(self) == 0) return PyBool_FromLong(0); e = p + PyString_GET_SIZE(self); // cased变量用于判断字符串中, // 是否存在大小写敏感的字符。 // 如果没有大小写敏感的字符, // 将返回False cased = 0; // previous_is_cased变量用于判断 // 当前的字母是否是单词的首字母。 previous_is_cased = 0; for (; p < e; p++) { register const unsigned char ch = *p; // 每个单词的首字母必须是大写字母。 if (isupper(ch)) { if (previous_is_cased) return PyBool_FromLong(0); previous_is_cased = 1; cased = 1; } // 每个单词的除首字母以外的其他字母 // 则必须是小写字母。 else if (islower(ch)) { if (!previous_is_cased) return PyBool_FromLong(0); previous_is_cased = 1; cased = 1; } // 非大小写敏感的字符则用于分隔单词, // 通过将previous_is_cased重置为0, // 从而可以让下一个大小写敏感的字符成为 // 下一个单词的首字母。 else previous_is_cased = 0; } return PyBool_FromLong(cased); } |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> 'Hello World Android123Haha'.istitle() True >>> 'H'.istitle() True >>> 'hello World'.istitle() False >>> 'h'.istitle() False >>> 'HeLlo'.istitle() False >>> 'Hello'.istitle() True >>> 'He;Lo'.istitle() True >>> quit() [email protected]:~$ |
static PyObject * string_join(PyStringObject *self, PyObject *orig) { // join方法的self主体字符串被用作分隔字符串 char *sep = PyString_AS_STRING(self); const Py_ssize_t seplen = PyString_GET_SIZE(self); ................................................ // orig是join方法的第一个参数, // 也就是join方法需要操作的集合 seq = PySequence_Fast(orig, ""); if (seq == NULL) { return NULL; } // 获取集合里的元素个数 seqlen = PySequence_Size(seq); // 当集合中的元素个数为0,也就是空集合时, // 直接返回一个空字符串 if (seqlen == 0) { Py_DECREF(seq); return PyString_FromString(""); } // 当集合中只有一个元素,且该元素为 // 字符串对象时,直接将该字符串对象返回 if (seqlen == 1) { item = PySequence_Fast_GET_ITEM(seq, 0); if (PyString_CheckExact(item) || PyUnicode_CheckExact(item)) { Py_INCREF(item); Py_DECREF(seq); return item; } } ................................................ for (i = 0; i < seqlen; i++) { const size_t old_sz = sz; item = PySequence_Fast_GET_ITEM(seq, i); // 集合里的每个元素都必须是字符串类型, // 否则会抛出TypeError即类型错误 if (!PyString_Check(item)){ ............................................... PyErr_Format(PyExc_TypeError, "sequence item %zd: expected string," " %.80s found", i, Py_TYPE(item)->tp_name); Py_DECREF(seq); return NULL; } // 将集合中每个字符串的尺寸都统计到sz变量里, // 同时将seplen即分隔字符串的尺寸也统计到sz中, // 下面会通过sz的值来创建需要返回的结果字符串对象 sz += PyString_GET_SIZE(item); if (i != 0) sz += seplen; ............................................... } // 根据sz的值来创建结果字符串对象 /* Allocate result space. */ res = PyString_FromStringAndSize((char*)NULL, sz); if (res == NULL) { Py_DECREF(seq); return NULL; } /* Catenate everything. */ p = PyString_AS_STRING(res); // 将集合里的每个字符串都拷贝到结果字符串中, // 同时将sep分隔字符串也拷贝到结果字符串里, // 集合的每个字符串之间通过分隔字符串隔开 for (i = 0; i < seqlen; ++i) { size_t n; item = PySequence_Fast_GET_ITEM(seq, i); n = PyString_GET_SIZE(item); Py_MEMCPY(p, PyString_AS_STRING(item), n); p += n; if (i < seqlen - 1) { Py_MEMCPY(p, sep, seplen); p += seplen; } } Py_DECREF(seq); // 将结果字符串对象返回 return res; } |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> '--'.join([]) '' >>> '--'.join(['hello']) 'hello' >>> '--'.join(['hello', 'world']) 'hello--world' >>> '--'.join(['aa', 'bb', 'cc', 'dd', 'ee']) 'aa--bb--cc--dd--ee' >>> '*-*'.join(['aa', 'bb', 'cc', 'dd', 'ee']) 'aa*-*bb*-*cc*-*dd*-*ee' >>> '*-*'.join(['aa', 'bb', 'cc', 'dd', 123]) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: sequence item 4: expected string, int found >>> quit() [email protected]:~$ |
static Py_ssize_t string_length(PyStringObject *a) { return Py_SIZE(a); } |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> len('hello') 5 >>> len('hello world') 11 >>> quit() [email protected]:~$ |
static PyObject * string_ljust(PyStringObject *self, PyObject *args) { Py_ssize_t width; // 默认的填充字符为空格符 char fillchar = ' '; // 从脚本中获取width宽度信息和fillchar填充字符 // fillchar为可选参数,如果没提供的话, // 就使用默认的空格符 if (!PyArg_ParseTuple(args, "n|c:ljust", &width, &fillchar)) return NULL; // 当width参数小于等于self主体字符串的字符个数时, // 直接将self字符串对象返回 if (PyString_GET_SIZE(self) >= width && PyString_CheckExact(self)) { Py_INCREF(self); return (PyObject*) self; } // 通过pad函数,创建一个self的copy拷贝字符串对象, // width - PyString_GET_SIZE(self)作为pad函数的第三个参数,表示: // 需要对copy字符串的右侧填充多少个fillchar字符, // 通过右侧填充,让copy字符串进行左对齐, // 最后将copy字符串对象返回。 return pad(self, 0, width - PyString_GET_SIZE(self), fillchar); } .................................................... static PyObject * string_rjust(PyStringObject *self, PyObject *args) { Py_ssize_t width; char fillchar = ' '; if (!PyArg_ParseTuple(args, "n|c:rjust", &width, &fillchar)) return NULL; if (PyString_GET_SIZE(self) >= width && PyString_CheckExact(self)) { Py_INCREF(self); return (PyObject*) self; } // 通过pad函数,创建一个self的copy拷贝字符串对象, // width - PyString_GET_SIZE(self)作为pad函数的第二个参数,表示: // 需要对copy字符串的左侧填充多少个fillchar字符, // 通过左侧填充,让copy字符串进行右对齐, // 最后将copy字符串对象返回。 return pad(self, width - PyString_GET_SIZE(self), 0, fillchar); } |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> 'hello'.ljust(11) 'hello ' >>> 'hello'.ljust(11, '-') 'hello------' >>> 'hello'.ljust(3) 'hello' >>> 'hello'.rjust(11) ' hello' >>> 'hello'.rjust(11, '-') '------hello' >>> 'hello'.rjust(3) 'hello' >>> quit() [email protected]:~$ |
#ifndef _tolower #define _tolower tolower #endif static PyObject * string_lower(PyStringObject *self) { char *s; Py_ssize_t i, n = PyString_GET_SIZE(self); PyObject *newobj; // 根据self主体字符串的尺寸, // 创建一个新的copy字符串对象 newobj = PyString_FromStringAndSize(NULL, n); if (!newobj) return NULL; // 得到copy字符串对象的字符串指针, // 该指针指向了具体的字符串数据 s = PyString_AS_STRING(newobj); // 将原self字符串对象里的字符串数据, // 拷贝到新的copy字符串中 Py_MEMCPY(s, PyString_AS_STRING(self), n); // 将copy字符串里的所有大写字母都转为 // 对应的小写字母。 for (i = 0; i < n; i++) { int c = Py_CHARMASK(s[i]); if (isupper(c)) s[i] = _tolower(c); } return newobj; } .................................................... #ifndef _toupper #define _toupper toupper #endif static PyObject * string_upper(PyStringObject *self) { char *s; Py_ssize_t i, n = PyString_GET_SIZE(self); PyObject *newobj; // 根据self主体字符串的尺寸, // 创建一个新的copy字符串对象 newobj = PyString_FromStringAndSize(NULL, n); if (!newobj) return NULL; // 得到copy字符串对象的字符串指针, // 该指针指向了具体的字符串数据 s = PyString_AS_STRING(newobj); // 将原self字符串对象里的字符串数据, // 拷贝到新的copy字符串中 Py_MEMCPY(s, PyString_AS_STRING(self), n); // 将copy字符串里的所有小写字母都转为 // 对应的大写字母。 for (i = 0; i < n; i++) { int c = Py_CHARMASK(s[i]); if (islower(c)) s[i] = _toupper(c); } return newobj; } |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> 'HELLO WORLD!'.lower() 'hello world!' >>> 'hello world!'.upper() 'HELLO WORLD!' >>> quit() [email protected]:~$ |
Py_LOCAL_INLINE(PyObject *) do_xstrip(PyStringObject *self, int striptype, PyObject *sepobj) { char *s = PyString_AS_STRING(self); Py_ssize_t len = PyString_GET_SIZE(self); char *sep = PyString_AS_STRING(sepobj); Py_ssize_t seplen = PyString_GET_SIZE(sepobj); Py_ssize_t i, j; i = 0; // striptype != RIGHTSTRIP表示当需要剔除左侧的字符时,或者 // 当需要将左右两侧的字符都剔除掉时,就执行if里的循环语句。 // sep字符串中的每个字符,都是需要剔除掉的字符, // s为原self字符串对象的字符串指针, // 循环判断self左侧的字符是否存在于sep字符串中, // 如果左侧的字符存在于sep里,就将i加一,也就是 // 跳过该字符,这样就间接的剔除掉了该字符, // 因为i会作为最后截取字符串片段操作时的起始位置。 // 直到self在左侧遇到一个非sep字符串中的字符时, // 才跳出循环 if (striptype != RIGHTSTRIP) { while (i < len && memchr(sep, Py_CHARMASK(s[i]), seplen)) { i++; } } j = len; // 如果需要将右侧的字符给剔除掉时, // 就将self右侧的字符分别与sep字符串中的字符进行比较, // 当右侧的字符存在于sep字符串中时,就将j减一, // 也就是将该字符给剔除掉,因为j会作为最后截取字符串 // 片段操作时的结束位置。 // 直到self在右侧遇到一个非sep字符串中的字符时,才跳出循环。 if (striptype != LEFTSTRIP) { do { j--; } while (j >= i && memchr(sep, Py_CHARMASK(s[j]), seplen)); j++; } if (i == 0 && j == len && PyString_CheckExact(self)) { Py_INCREF(self); return (PyObject*)self; } else // 根据i和j的值,对self字符串进行截取操作。 // 将i到j的字符串片段给截取出来 // (当然返回的会是一个新的字符串对象), // 通过截取操作,原self左右两侧的需要剔除的字符, // 就自动被截掉了。 return PyString_FromStringAndSize(s+i, j-i); } Py_LOCAL_INLINE(PyObject *) do_strip(PyStringObject *self, int striptype) { char *s = PyString_AS_STRING(self); Py_ssize_t len = PyString_GET_SIZE(self), i, j; i = 0; // 当需要剔除左侧的空白字符时, // 循环通过isspace来判断左侧是否是空白字符, // 如果是空白字符就将起始位置i加一, // isspace是C标准的库函数。 if (striptype != RIGHTSTRIP) { while (i < len && isspace(Py_CHARMASK(s[i]))) { i++; } } j = len; // 当需要剔除右侧的空白字符时, // 循环通过isspace来判断右侧是否是空白字符, // 如果是空白字符就将结束位置j减一, if (striptype != LEFTSTRIP) { do { j--; } while (j >= i && isspace(Py_CHARMASK(s[j]))); j++; } if (i == 0 && j == len && PyString_CheckExact(self)) { Py_INCREF(self); return (PyObject*)self; } else // 通过i和j来截取字符串片段,从而将 // 左侧或右侧的空白字符给剔除掉。 return PyString_FromStringAndSize(s+i, j-i); } Py_LOCAL_INLINE(PyObject *) do_argstrip(PyStringObject *self, int striptype, PyObject *args) { PyObject *sep = NULL; if (!PyArg_ParseTuple(args, (char *)stripformat[striptype], &sep)) return NULL; if (sep != NULL && sep != Py_None) { // 如果提供了sep(其中包含了需要剔除的字符)时, // 就通过上面的do_xstrip函数,将左侧或右侧的 // 存在于sep中的字符给剔除掉。 // striptype的值可以是LEFTSTRIP(表示剔除掉左侧的字符), // RIGHTSTRIP(表示剔除掉右侧的字符) // 或者是BOTHSTRIP(表示剔除掉左右两侧的字符) if (PyString_Check(sep)) return do_xstrip(self, striptype, sep); ................................................ } // 如果没提供sep,则通过do_strip函数 // 将左侧或右侧的空白字符给剔除掉。 return do_strip(self, striptype); } .................................................... static PyObject * string_strip(PyStringObject *self, PyObject *args) { // 如果strip方法没提供参数的话, // 就通过do_strip函数将左右两侧的空白字符 // 给剔除掉。 if (PyTuple_GET_SIZE(args) == 0) return do_strip(self, BOTHSTRIP); /* Common case */ else // 如果提供了参数,就通过 // do_argstrip函数将包含在参数中的 // 左右两侧的字符给剔除掉 return do_argstrip(self, BOTHSTRIP, args); } .................................................... static PyObject * string_lstrip(PyStringObject *self, PyObject *args) { // lstrip方法就是将左侧的字符给剔除掉 if (PyTuple_GET_SIZE(args) == 0) return do_strip(self, LEFTSTRIP); /* Common case */ else return do_argstrip(self, LEFTSTRIP, args); } .................................................... static PyObject * string_rstrip(PyStringObject *self, PyObject *args) { // rstrip方法就是将右侧的字符给剔除掉 if (PyTuple_GET_SIZE(args) == 0) return do_strip(self, RIGHTSTRIP); /* Common case */ else return do_argstrip(self, RIGHTSTRIP, args); } |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> ' \r\n\f\t\v\t hello world'.lstrip() 'hello world' >>> '--+++---****--/////hello world'.lstrip('+-*/') 'hello world' >>> 'hello world \r\v\t\f\f\n\n '.rstrip() 'hello world' >>> 'hello world--+++---****--/////'.rstrip('+-*/') 'hello world' >>> ' \r\n\f\t\v\t hello world \r\r\n\n\t\t\f\f'.strip() 'hello world' >>> '++-----====~~hello world!!!!~~~~'.strip('-+=~!') 'hello world' >>> quit() [email protected]:~$ |
.................................................... l = map(chr, xrange(256)) _idmap = str('').join(l) del l .................................................... # Construct a translation string _idmapL = None def maketrans(fromstr, tostr): """maketrans(frm, to) -> string Return a translation table (a string of 256 bytes long) suitable for use in string.translate. The strings frm and to must be of the same length. """ if len(fromstr) != len(tostr): raise ValueError, "maketrans arguments must have same length" global _idmapL if not _idmapL: _idmapL = list(_idmap) L = _idmapL[:] fromstr = map(ord, fromstr) for i in range(len(fromstr)): L[fromstr[i]] = tostr[i] return ''.join(L) |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import string >>> string._idmap '.............................................. ............................................... \x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmn opqrstuvwxyz{|}~............................... ............................................... .............................................' >>> quit() [email protected]:~$ |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import string >>> string._idmap '.............................................. ............................................... \x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmn opqrstuvwxyz{|}~............................... ............................................... .............................................' >>> string.maketrans('ABCD', '1234') '.............................................. ............................................... \x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ 1234EFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmn opqrstuvwxyz{|}~............................... ............................................... ...............................................' >>> quit() [email protected]:~$ |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import string >>> table = string.maketrans('ABCD', '1234') >>> table '.............................................. ............................................... \x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ 1234EFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmn opqrstuvwxyz{|}~............................... ............................................... ...............................................' >>> 'AABBCCDD hello'.translate(table) '11223344 hello' >>> quit() [email protected]:~$ |
PyDoc_STRVAR(translate__doc__, "S.translate(table [,deletechars]) -> string\n\ \n\ Return a copy of the string S, where all characters occurring\n\ in the optional argument deletechars are removed, and the\n\ remaining characters have been mapped through the given\n\ translation table, which must be a string of length 256 or None.\n\ If the table argument is None, no translation is applied and\n\ the operation simply removes the characters in deletechars."); static PyObject * string_translate(PyStringObject *self, PyObject *args) { ................................................ // 将脚本的第一个参数设置到tableobj中, // 将脚本的第二个参数设置到delobj中,其中, // 第一个参数为必须提供的参数, // 第二个参数为可选参数,两个参数都必须是字符串对象, // delobj对象所对应的字符串中的每个字符都是需要被 // 删除掉的字符。 if (!PyArg_UnpackTuple(args, "translate", 1, 2, &tableobj, &delobj)) return NULL; // 将tableobj字符串对象的字符串指针设置到table变量, // 同时将tableobj字符串对象所包含的字符个数设置到tablen变量中。 if (PyString_Check(tableobj)) { table = PyString_AS_STRING(tableobj); tablen = PyString_GET_SIZE(tableobj); } // 如果第一个参数是None的话,则将table设置为空指针。 else if (tableobj == Py_None) { table = NULL; tablen = 256; } ................................................ // table字符串中必须包含256个字符 if (tablen != 256) { PyErr_SetString(PyExc_ValueError, "translation table must be 256 characters long"); return NULL; } // 获取delobj字符串对象所对应的字符串指针与 // 该字符串所包含的字符个数。 if (delobj != NULL) { if (PyString_Check(delobj)) { del_table = PyString_AS_STRING(delobj); dellen = PyString_GET_SIZE(delobj); } ............................................. } else { del_table = NULL; dellen = 0; } // 获取主体字符串的长度信息。 inlen = PyString_GET_SIZE(input_obj); // 根据主体字符串的长度, // 来创建需要返回的result结果字符串对象。 result = PyString_FromStringAndSize((char *)NULL, inlen); if (result == NULL) return NULL; // 将结果字符串对象的字符串指针设置到output变量。 output_start = output = PyString_AsString(result); // 获取主体字符串对象的字符串指针。 input = PyString_AS_STRING(input_obj); // 当dellen == 0,且table不为空指针时, // 直接根据table字符串来做映射处理。 if (dellen == 0 && table != NULL) { /* If no deletions are required, use faster code */ for (i = inlen; --i >= 0; ) { c = Py_CHARMASK(*input++); // 使用主体字符串中的字符的ASCII码作为索引值, // 从table字符串里得到对应的字符,并映射 // 到output即结果字符串里。 if (Py_CHARMASK((*output++ = table[c])) != c) changed = 1; } // 如果table字符串对应的ASCII码表被修改了, // 则将result结果字符串对象返回。 if (changed || !PyString_CheckExact(input_obj)) return result; // 如果table字符串对应的ASCII码表没被修改的话, // 也就是table里的每个字符的ASCII码都等于该字符在 // table字符串中的索引值(或者叫偏移值)时, // 则直接将主体字符串对象返回,同时增加主体字符串对象的 // 引用计数。 Py_DECREF(result); Py_INCREF(input_obj); return input_obj; } // 当dellen不等于0,或者table为空指针时, // 则执行下面的代码。 // 先将table字符串里的字符拷贝到trans_table中, // 如果table为空指针的话,则直接将0到256的ASCII码值 // 拷贝到trans_table中。 if (table == NULL) { for (i = 0; i < 256; i++) trans_table[i] = Py_CHARMASK(i); } else { for (i = 0; i < 256; i++) trans_table[i] = Py_CHARMASK(table[i]); } // 如果dellen不等于0(即有需要删除的字符时),则 // 将trans_table中需要删除的字符设置为-1 for (i = 0; i < dellen; i++) trans_table[(int) Py_CHARMASK(del_table[i])] = -1; for (i = inlen; --i >= 0; ) { c = Py_CHARMASK(*input++); // 如果trans_table[c]等于-1的话, // 说明该字符需要被删除掉,则不会将 // trans_table[c]设置到output结果字符串里, // 如果trans_table[c]不为-1的话, // 则将trans_table[c]设置到output中 if (trans_table[c] != -1) if (Py_CHARMASK(*output++ = (char)trans_table[c]) == c) continue; changed = 1; } // 如果trans_table对应的ASCII码表没发生修改的话, // 则直接将input_obj主体字符串对象返回。 if (!changed && PyString_CheckExact(input_obj)) { Py_DECREF(result); Py_INCREF(input_obj); return input_obj; } // 通过_PyString_Resize来调整result结果字符串的尺寸, // 因为在上面可能删除了某些字符,从而让实际的尺寸小于分配的尺寸, // _PyString_Resize函数就可以针对这种情况来调整尺寸。 /* Fix the size of the resulting string */ if (inlen > 0 && _PyString_Resize(&result, output - output_start)) return NULL; // 将result结果字符串对象返回 return result; } |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import string >>> table = string.maketrans('ABCD', '1234') >>> 'AABBCCDD hello'.translate(table, 'hl') '11223344 eo' >>> 'AABBCCDD hello'.translate(None, 'hl') 'AABBCCDD eo' >>> 'AABBCCDD hello'.translate(None) 'AABBCCDD hello' >>> 'AABBCCDD hello'.translate('abcd') Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: translation table must be 256 characters long >>> quit() [email protected]:~$ |
static PyObject * min_max(PyObject *args, PyObject *kwds, int op) { PyObject *v, *it, *item, *val, *maxitem, *maxval, *keyfunc=NULL; const char *name = op == Py_LT ? "min" : "max"; // 可以给min与max方法提供多个参数, // 当提供了多个参数时,就在这些参数之间 // 进行比较,并返回最大值或最小值, // 当op为Py_LT时,返回最小值, // 当op为Py_GT时,返回最大值, // 注意这些参数并不包括kwds词典在内 // 例如: max('a', 'b', key=keyfunc) // 其中'a','b'会构成此处的args元组, // 而key=keyfunc则成为kwds词典里的成员, // 此时kwds词典里只有一个成员,该成员 // 的key就是'key',对应的值为keyfunc // 又例如: max('a','b',key=keyfunc,max='hello') // 那么'a','b'依旧是构成args元组, // 但此时的kwds词典中就有了两个成员, // 一个是key->keyfunc即key为'key',值为keyfunc的成员, // 另一个则是max->'hello'即key为'max',值为'hello'的成员 if (PyTuple_Size(args) > 1) v = args; // 当只提供了一个参数时,则只会对该参数的 // 内部的元素进行比较, // 例如: max('abcd')执行时,就只会对'abcd'字符串内部 // 的4个字符'a','b','c','d'进行比较。 else if (!PyArg_UnpackTuple(args, (char *)name, 1, 1, &v)) return NULL; // 将kwds词典中key为"key"的成员所对应的值提取出来, // 作为keyfunc,keyfunc的作用就是将需要比较的元素转换为 // 实际进行比较的值。 // 例如: // >>> def keyfunc(item): // ... if(item == 'a'): // ... return '2' // ... elif(item == 'b'): // ... return '1' // ... // >>> max('ab', key = keyfunc) // 'a' // 上面例子中,'a'在keyfunc的作用下会转为'2',而 // 'b'在keyfunc的作用下则会转为'1',因此,该例子中, // 'a'与'b'之间的比较就转为了'2'与'1'之间的比较, // 由于'2'的ASCII码大于'1',因此结果就显示'a'最大, // 但其实'a'的ASCII码是小于'b'的,只不过实际比较时, // 不是用的'a','b'的ASCII码来比较的,是用的 // '2'和'1'来进行比较的。 if (kwds != NULL && PyDict_Check(kwds) && PyDict_Size(kwds)) { keyfunc = PyDict_GetItemString(kwds, "key"); if (PyDict_Size(kwds)!=1 || keyfunc == NULL) { PyErr_Format(PyExc_TypeError, "%s() got an unexpected keyword argument", name); return NULL; } Py_INCREF(keyfunc); } it = PyObject_GetIter(v); if (it == NULL) { Py_XDECREF(keyfunc); return NULL; } maxitem = NULL; /* the result */ maxval = NULL; /* the value associated with the result */ while (( item = PyIter_Next(it) )) { // 如果提供了keyfunc,则从keyfunc中获取到 // 实际需要进行比较的值来。 /* get the value from the key function */ if (keyfunc != NULL) { val = PyObject_CallFunctionObjArgs(keyfunc, item, NULL); if (val == NULL) goto Fail_it_item; } // 如果没提供keyfunc,则使用原始的值来进行比较。 /* no key function; the value is the item */ else { val = item; Py_INCREF(val); } /* maximum value and item are unset; set them */ if (maxval == NULL) { maxitem = item; maxval = val; } /* maximum value and item are set; update them as necessary */ else { // 根据op对val与maxval进行比较, // 如果是Py_LT操作(也就是获取最小值的操作)时, // 则当val小于maxval时,val就作为新的maxval, // 如果是Py_GT(也就是获取最大值的操作)时, // 则当val大于maxval时,val就作为新的maxval, // 对于字符串对象,PyObject_RichCompareBool最终会 // 通过Objects/stringobject.c文件中的 // string_richcompare函数来完成具体的比较操作。 int cmp = PyObject_RichCompareBool(val, maxval, op); if (cmp < 0) goto Fail_it_item_and_val; else if (cmp > 0) { Py_DECREF(maxval); Py_DECREF(maxitem); maxval = val; maxitem = item; } else { Py_DECREF(item); Py_DECREF(val); } } } if (PyErr_Occurred()) goto Fail_it; if (maxval == NULL) { PyErr_Format(PyExc_ValueError, "%s() arg is an empty sequence", name); assert(maxitem == NULL); } else Py_DECREF(maxval); Py_DECREF(it); Py_XDECREF(keyfunc); // 将最大值或最小值返回 return maxitem; ..................................................... } static PyObject * builtin_min(PyObject *self, PyObject *args, PyObject *kwds) { return min_max(args, kwds, Py_LT); } ..................................................... static PyObject * builtin_max(PyObject *self, PyObject *args, PyObject *kwds) { return min_max(args, kwds, Py_GT); } |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> def keyfunc(item): ... if(item == 'a'): ... return '2' ... elif(item == 'b'): ... return '1' ... >>> max('ab', key = keyfunc) 'a' >>> max('a', 'b') 'b' >>> max('a', 'b', key=keyfunc) 'a' >>> max('abc', 'ABC') 'abc' >>> min('abc', 'ABC') 'ABC' >>> max('abC', 'abc') 'abc' >>> min('abC', 'abc') 'abC' >>> max('hello', 'world', 'zengl.com') 'zengl.com' >>> min('hello', 'world', 'zengl.com') 'hello' >>> quit() [email protected]:~$ |
// 下面的replace_substring_in_place函数只会在 // from_s与to_s长度相同时,才使用的。 /* len(self)>=1, len(from)==len(to)>=2, maxcount>=1 */ Py_LOCAL(PyStringObject *) replace_substring_in_place(PyStringObject *self, const char *from_s, Py_ssize_t from_len, const char *to_s, Py_ssize_t to_len, Py_ssize_t maxcount) { ................................................ // 下面的self_s是主体字符串, // from_s是主体字符串里需要被替换掉的子字符串, // 先通过stringlib_find查找出from_s在self_s中的 // offset偏移值,这样,后面就可以通过该偏移值, // 将to_s拷贝到offset位置处, // 从而完成用to_s替换from_s的操作。 // 当然开头的替换操作只能对第一个from_s进行替换, // 最后还有一个while循环语句,会利用相同的原理, // 将self_s中剩余的from_s都替换为to_s, // 至于一共要替换多少次,则是由maxcount参数来决定的。 offset = stringlib_find(self_s, self_len, from_s, from_len, 0); ................................................ // 返回的是一个新创建的字符串对象 /* Need to make a new string */ result = (PyStringObject *) PyString_FromStringAndSize(NULL, self_len); if (result == NULL) return NULL; result_s = PyString_AS_STRING(result); // 将主体字符串的原始数据全部拷贝到结果字符串中 Py_MEMCPY(result_s, self_s, self_len); /* change everything in-place, starting with this one */ start = result_s + offset; // 根据offset偏移值(此处已转换为了start指针), // 将to_s拷贝到start位置处,覆盖掉原来的 // from_s,由于to_s与from_s的长度相同, // 因此,覆盖替换操作,不会对结果字符串的长度产生影响。 Py_MEMCPY(start, to_s, from_len); start += from_len; end = result_s + self_len; // 根据maxcount将余下的from_s都替换为to_s while ( --maxcount > 0) { offset = stringlib_find(start, end-start, from_s, from_len, 0); if (offset==-1) break; Py_MEMCPY(start+offset, to_s, from_len); start += offset+from_len; } return result; } .................................................... // 当from_s与to_s长度不同时,则会使用下面的函数来完成替换工作 /* len(self)>=1, len(from)>=2, len(to)>=2, maxcount>=1 */ Py_LOCAL(PyStringObject *) replace_substring(PyStringObject *self, const char *from_s, Py_ssize_t from_len, const char *to_s, Py_ssize_t to_len, Py_ssize_t maxcount) { ................................................ // 在from_s与to_s长度不同的情况下, // 就需要将主体字符串分段拷贝到结果字符串中 // 例如: 'hello hello'.replace('ll', 'mnz')在执行时, // 会先创建一个结果字符串对象, // 然后先将主体字符串里的'he'拷贝到结果字符串,此时的 // 结果字符串变为'he',再将'mnz'拷贝到结果字符串,此时的 // 结果字符串变为'hemnz',再接着将'o he'拷贝到结果字符串, // 此时的结果字符串就变为'hemnzo he',接着再将'mnz' // 拷贝到结果字符串,结果字符串就变为'hemnzo hemnz', // 最后将剩下的'o'拷贝到结果字符串,结果字符串最终就变为 // 'hemnzo hemnzo',这样,'ll'就替换为'mnz'了。 while (count-- > 0) { // 从start位置处开始,查找出from_s在主体字符串 // 里的相对于start的offset偏移值 offset = stringlib_find(start, end-start, from_s, from_len, 0); // 如果找不到则直接跳出循环 if (offset == -1) break; next = start+offset; if (next == start) { // 如果from_s位于主体字符串的起始位置的话, // 则直接将to_s拷贝到result_s结果字符串 // 的起始位置处。 /* replace with the 'to' */ Py_MEMCPY(result_s, to_s, to_len); // 重新设置result_s与start指针,为下一次的 // 查找与拷贝操作,做准备。 result_s += to_len; start += from_len; } else { // 如果from_s位于主体字符串的中间位置, // 则先将from_s之前的主体字符串里的数据 // 拷贝到结果字符串中 /* copy the unchanged old then the 'to' */ Py_MEMCPY(result_s, start, next-start); result_s += (next-start); // 再将to_s拷贝到结果字符串 Py_MEMCPY(result_s, to_s, to_len); // 重新设置result_s与start指针,为下一次的 // 查找与拷贝操作,做准备。 result_s += to_len; start = next+from_len; } } // 将主体字符串中,余下的数据拷贝到结果字符串。 /* Copy the remainder of the remaining string */ Py_MEMCPY(result_s, start, end-start); return result; } Py_LOCAL(PyStringObject *) replace(PyStringObject *self, const char *from_s, Py_ssize_t from_len, const char *to_s, Py_ssize_t to_len, Py_ssize_t maxcount) { if (maxcount < 0) { maxcount = PY_SSIZE_T_MAX; } else if (maxcount == 0 || PyString_GET_SIZE(self) == 0) { /* nothing to do; return the original string */ return return_self(self); } ................................................ if (from_len == to_len) { if (from_len == 1) { return replace_single_character_in_place( self, from_s[0], to_s[0], maxcount); } else { return replace_substring_in_place( self, from_s, from_len, to_s, to_len, maxcount); } } /* Otherwise use the more generic algorithms */ if (from_len == 1) { return replace_single_character(self, from_s[0], to_s, to_len, maxcount); } else { /* len('from')>=2, len('to')>=1 */ return replace_substring(self, from_s, from_len, to_s, to_len, maxcount); } } static PyObject * string_replace(PyStringObject *self, PyObject *args) { // count的缺省值为-1,该值(小于0时)会在上面的replace函数中被转换为PY_SSIZE_T_MAX, // PY_SSIZE_T_MAX是一个很大的数,就表示将主体字符串里的所有需要替换的字符串都替换掉。 Py_ssize_t count = -1; ................................................ // replace方法的第一个from与第二个to参数是必须提供的参数, // 表示需要将主体字符串里的from字符串替换为to字符串, // 第三个count参数表示最多替换多少次。缺省值为-1,表示将所有的from都替换为to。 if (!PyArg_ParseTuple(args, "OO|n:replace", &from, &to, &count)) return NULL; ................................................ // 最后通过上面的replace函数来完成具体的替换操作。 return (PyObject *)replace((PyStringObject *) self, from_s, from_len, to_s, to_len, count); } |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> 'hello'.replace('ll', 'mn') 'hemno' >>> 'hello hello'.replace('ll', 'mnz') 'hemnzo hemnzo' >>> 'hello hello hello'.replace('ll', 'mn', 2) 'hemno hemno hello' >>> 'hello hello hello'.replace('ll', 'mn', 1) 'hemno hello hello' >>> 'hello hello'.replace('ll', 'mnz', 1) 'hemnzo hello' >>> 'hello hello'.replace('ll', 'mnz', 0) 'hello hello' >>> 'hello hello'.replace('ll', 'mnz', -1) 'hemnzo hemnzo' >>> 'hello hello'.replace('ll', 'mnz', -2) 'hemnzo hemnzo' >>> quit() [email protected]:~$ |
PyDoc_STRVAR(split__doc__, "S.split([sep [,maxsplit]]) -> list of strings\n\ \n\ Return a list of the words in the string S, using sep as the\n\ delimiter string. If maxsplit is given, at most maxsplit\n\ splits are done. If sep is not specified or is None, any\n\ whitespace string is a separator and empty strings are removed\n\ from the result."); static PyObject * string_split(PyStringObject *self, PyObject *args) { Py_ssize_t len = PyString_GET_SIZE(self), n; Py_ssize_t maxsplit = -1; const char *s = PyString_AS_STRING(self), *sub; PyObject *subobj = Py_None; // 从脚本中获取到split方法的两个参数, // 将第一个参数设置到subobj变量, // 并将第二个参数设置到maxsplit变量, // 这两个参数都是可选参数,subobj的缺省值是None, // maxsplit的缺省值是-1,这两个缺省值是在函数的开头 // 就已经被设置好了的。 // split方法会使用subobj作为分割字符串, // 将self主体字符串分割为多个字符串所构成的列表, // 例如: 'aa--bb--cc--dd'.split('--')脚本执行后, // 得到的结果就会是: ['aa', 'bb', 'cc', 'dd'] 。 // maxsplit表示最多分割多少次, // 例如: 'aa--bb--cc--dd'.split('--', 2)得到的结果 // 就是: ['aa', 'bb', 'cc--dd'],也就是最多只分割两次。 if (!PyArg_ParseTuple(args, "|On:split", &subobj, &maxsplit)) return NULL; // 当maxsplit的值小于0时, // 就将其设置为PY_SSIZE_T_MAX, // PY_SSIZE_T_MAX是一个很大的数, // 因此,缺省情况下,就是将所有能分割 // 的字符串都进行分割。 if (maxsplit < 0) maxsplit = PY_SSIZE_T_MAX; // 当subobj为None时,就通过 // stringlib_split_whitespace函数 // 使用空白字符来进行分割。 // 例如: 'aa \n\rbb\f\fcc\v\v\rdd'.split()得到的 // 结果就是: ['aa', 'bb', 'cc', 'dd'] // stringlib_split_whitespace函数定义在 // Objects/stringlib/split.h的文件中 if (subobj == Py_None) return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit); // 如果subobj不为None,且subobj是一个 // 有效的字符串对象,则使用subobj来作为分割字符串。 // 下面的sub是subobj对象的字符串指针, // 下面的n则是subobj对象的字符串数据 // 所包含的字符个数。 if (PyString_Check(subobj)) { sub = PyString_AS_STRING(subobj); n = PyString_GET_SIZE(subobj); } ................................................ // 使用stringlib_split函数,根据sub字符串, // 将self主体字符串最多分割maxsplit次,分割后, // 得到的列表作为结果返回。 // stringlib_split函数定义在 // Objects/stringlib/split.h的文件中。 return stringlib_split((PyObject*) self, s, len, sub, n, maxsplit); } .................................................... PyDoc_STRVAR(splitlines__doc__, "S.splitlines(keepends=False) -> list of strings\n\ \n\ Return a list of the lines in S, breaking at line boundaries.\n\ Line breaks are not included in the resulting list unless keepends\n\ is given and true."); static PyObject* string_splitlines(PyStringObject *self, PyObject *args) { int keepends = 0; // splitlines方法用于将self里的多行字符串, // 根据换行符来进行分割,分割所形成的列表作为结果返回。 // keepends参数为可选参数,缺省值为0, // 当脚本提供的参数为布尔对象时, // True在此处会被转为1,False则被转为0, // 当keepends为0时,不会保留换行符。 // 当keepends不为0时,则会将换行符保留下来。 // 例如: 'hello\r\nhello'.splitlines(False)执行后, // 得到的结果就是: ['hello', 'hello'] , // 又例如: 'hello\r\nhello'.splitlines(True)执行后, // 得到的结果就会是: ['hello\r\n', 'hello'] if (!PyArg_ParseTuple(args, "|i:splitlines", &keepends)) return NULL; // 最后通过stringlib_splitlines函数 // 来完成具体的分割操作, // 该函数定义在Objects/stringlib/split.h文件中。 return stringlib_splitlines( (PyObject*) self, PyString_AS_STRING(self), PyString_GET_SIZE(self), keepends ); } |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> 'aa--bb--cc--dd'.split('--') ['aa', 'bb', 'cc', 'dd'] >>> 'aa--bb--cc--dd'.split('--', 2) ['aa', 'bb', 'cc--dd'] >>> 'aa--bb--cc--dd'.split('--', 1) ['aa', 'bb--cc--dd'] >>> 'aa\r\nbb\v\vcc\f\f\t\tdd'.split(None, 2) ['aa', 'bb', 'cc\x0c\x0c\t\tdd'] >>> 'aa\r\nbb\v\vcc\f\f\t\tdd'.split(None) ['aa', 'bb', 'cc', 'dd'] >>> 'aa\r\nbb\v\vcc\f\f\t\tdd'.split() ['aa', 'bb', 'cc', 'dd'] >>> 'aa\r\nbb\v\vcc\f\f\t\tdd'.split(None, -3) ['aa', 'bb', 'cc', 'dd'] >>> 'aa\r\nbb\v\vcc\f\f\t\tdd'.split(None, 0) ['aa\r\nbb\x0b\x0bcc\x0c\x0c\t\tdd'] >>> 'hello\r\nhello'.splitlines(True) ['hello\r\n', 'hello'] >>> 'hello\r\nhello'.splitlines(False) ['hello', 'hello'] >>> 'hello\r\nhello'.splitlines() ['hello', 'hello'] >>> 'hello\r\nhello'.splitlines(-2) ['hello\r\n', 'hello'] >>> 'hello\r\nhello'.splitlines(-3) ['hello\r\n', 'hello'] >>> 'hello\r\nhello'.splitlines(0) ['hello', 'hello'] >>> 'hello\r\nhello'.splitlines(1) ['hello\r\n', 'hello'] >>> 'hello\r\nhello'.splitlines(2) ['hello\r\n', 'hello'] >>> 'hello\r\nhell\nhello'.splitlines() ['hello', 'hell', 'hello'] >>> 'hello\r\nhell\nhello'.splitlines(True) ['hello\r\n', 'hell\n', 'hello'] >>> 'hello\r\nhell\nhello'.splitlines(3) ['hello\r\n', 'hell\n', 'hello'] >>> quit() [email protected]:~$ |
PyDoc_STRVAR(swapcase__doc__, "S.swapcase() -> string\n\ \n\ Return a copy of the string S with uppercase characters\n\ converted to lowercase and vice versa."); static PyObject * string_swapcase(PyStringObject *self) { char *s = PyString_AS_STRING(self), *s_new; Py_ssize_t i, n = PyString_GET_SIZE(self); PyObject *newobj; // 根据self主体字符串的长度, // 创建一个新的copy字符串对象 newobj = PyString_FromStringAndSize(NULL, n); if (newobj == NULL) return NULL; // 得到copy字符串对象的数据指针 s_new = PyString_AsString(newobj); for (i = 0; i < n; i++) { int c = Py_CHARMASK(*s++); // 当主体字符串里的字符为小写字母时, // 就将其转为大写字母, // 并存储到结果字符串中。 if (islower(c)) { *s_new = toupper(c); } // 如果是大写字母,就转为小写字母。 else if (isupper(c)) { *s_new = tolower(c); } // 其他的字符则保持不变 else *s_new = c; s_new++; } // 将copy字符串对象作为结果返回 return newobj; } |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> 'Hello World ZenGl!!'.swapcase() 'hELLO wORLD zENgL!!' >>> quit() [email protected]:~$ |
PyDoc_STRVAR(title__doc__, "S.title() -> string\n\ \n\ Return a titlecased version of S, i.e. words start with uppercase\n\ characters, all remaining cased characters have lowercase."); // 为主体字符串创建一个标题样式的copy字符串, // 在标题样式中,所有单词的首字母都是大写字母, // 单词的其余字母则都是小写字母。 // 字符串中的非大小写敏感的字符, // 则起到分隔单词的作用, // 最后将该标题样式的copy字符串作为结果返回 static PyObject* string_title(PyStringObject *self) { char *s = PyString_AS_STRING(self), *s_new; Py_ssize_t i, n = PyString_GET_SIZE(self); int previous_is_cased = 0; PyObject *newobj; // 根据self主体字符串的数据长度, // 创建一个新的copy字符串对象 newobj = PyString_FromStringAndSize(NULL, n); if (newobj == NULL) return NULL; // 获取copy字符串对象的数据指针 s_new = PyString_AsString(newobj); for (i = 0; i < n; i++) { int c = Py_CHARMASK(*s++); // 将单词的首字母都设置为大写字母 if (islower(c)) { if (!previous_is_cased) c = toupper(c); previous_is_cased = 1; // 将单词的其余字母都设置为小写字母 } else if (isupper(c)) { if (previous_is_cased) c = tolower(c); previous_is_cased = 1; // 其他的非大小写敏感的字符, // 则起到分隔单词的作用 } else previous_is_cased = 0; *s_new++ = c; } // 将标题样式的copy字符串对象作为结果返回 return newobj; } |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> 'hello world android'.title() 'Hello World Android' >>> 'hel123lo wor~~ld zengl.com'.title() 'Hel123Lo Wor~~Ld Zengl.Com' >>> quit() [email protected]:~$ |
PyDoc_STRVAR(zfill__doc__, "S.zfill(width) -> string\n" "\n" "Pad a numeric string S with zeros on the left, to fill a field\n" "of the specified width. The string S is never truncated."); // 根据width宽度参数,在字符串的左侧填充'0'字符 static PyObject * string_zfill(PyStringObject *self, PyObject *args) { Py_ssize_t fill; PyObject *s; char *p; Py_ssize_t width; // 从脚本中获取width宽度信息,该参数是必填参数 if (!PyArg_ParseTuple(args, "n:zfill", &width)) return NULL; // 当width参数小于等于self主体字符串的字符个数时, // 直接将self字符串对象返回 if (PyString_GET_SIZE(self) >= width) { if (PyString_CheckExact(self)) { Py_INCREF(self); return (PyObject*) self; } else return PyString_FromStringAndSize( PyString_AS_STRING(self), PyString_GET_SIZE(self) ); } // 通过width - PyString_GET_SIZE(self) // 计算出fill值,也就是需要在字符串的左侧 // 填充多少个'0' fill = width - PyString_GET_SIZE(self); // 通过pad函数,创建一个self的copy拷贝字符串对象, // 并在copy字符串的左侧,填充fill个'0'字符 s = pad(self, fill, 0, '0'); if (s == NULL) return NULL; p = PyString_AS_STRING(s); // 将原字符串里的正负号放置到'0'字符的前面 // 不过只能将第一个'+'或'-'放置到最前方, // 例如: '++12345'.zfill(12)执行后,得到的结果 // 就会是: '+00000+12345' ,因为下面的代码 // 只对开头的'+'或'-'字符做了判断 if (p[fill] == '+' || p[fill] == '-') { /* move sign to beginning of string */ p[0] = p[fill]; p[fill] = '0'; } // 将copy字符串对象返回 return (PyObject*) s; } |
[email protected]:~$ python Python 2.7.8 (default, Feb 20 2015, 12:54:46) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> '++12345'.zfill(12) '+00000+12345' >>> 'hello'.zfill(9) '0000hello' >>> '-0.1234'.zfill(11) '-00000.1234' >>> '123456'.zfill(3) '123456' >>> quit() [email protected]:~$ |