python2中的字符串是byte的有序序列
python3中的字符串是unicode的有序序列
字符串是不可变的
字符串支持下标于切片
改变字符串,往往需要O(n)的时间复杂度,其中,n为新字符串的长度。
s = '' for n in range(0, 100000): s += str(n)
自从Python2.5开始,每次处理字符串的拼接操作时(str1 += str2),Python首先会检测str1还有没有其他的引用。如果没有的话,就会尝试原地扩充字符串buffer的大小,而不是重新分配一块内存来创建新的字符串并拷贝。这样的话,上述例子中的时间复杂度就仅为O(n)了。
在字符串前面加上r或者R前缀,表示该字符串不做特殊处理
r'\r \t \n'
里面所有的转译自负当作普通字符对待
In [1]: s = 'I love Python' In [2]: s[0] Out[2]: 'I' In [3]: s[-1] Out[3]: 'n' In [4]: s[3:8] Out[4]: 'ove P' In [5]: s[::-1] Out[5]: 'nohtyP evol I'
In [6]: s Out[6]: 'I love Python' In [7]: for i in s: ...: print(i) ...: I l o v e P y t h o n
字符串是不可变的 (元组也不可变)
In [8]: s Out[8]: 'I love Python' In [9]: s[1] Out[9]: ' ' In [10]: s[1] = '_' --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-10-8ab2d301e01f> in <module>() ----> 1 s[1] = '_' TypeError: 'str' object does not support item assignment
对象被多个变量所指向或者引用,由于int 和string 类型是不可变的,所以新创建的变量为新的,不会影响其他变量的值
变量的赋值,只是表示让变量指向了某个对象,并不表示拷贝对象给变量;而一个对象,可以被多个变量所指向。
对于不可变对象(字符串,整型,元祖等等),所有指向该对象的变量的值总是一样的,也不会改变。但是通过某些操作(+=等等)更新不可变对象的值时,会返回一个新的对象
变量可以被删除,但是对象无法被删除
In [5]: a = 1 In [6]: b = a In [7]: a = a + 1 In [8]: a Out[8]: 2 In [9]: b Out[9]: 1
print style format
format 方法
Print Style Format
template % tunple
template % dict
In [11]: 'I love %s' % ('python',) Out[11]: 'I love python' In [12]: 'I love %(name)s' % {'name':'python'} Out[12]: 'I love python'
Print Styple Format Conversation
符号 | 说明 |
---|---|
%d | 整数 |
%i | 整数 |
%o | 八进制数 |
%x | 小写16进制整数 |
%X | 大写16进制整数 |
%f | 浮点数 |
%F | 浮点数 |
%e | 小写科学计数法 |
%E | 大写科学计数法 |
%c | 字符,接收unicode编码或者单字符串 |
%a | 字符串,使用ascii函数转换 |
%r | 字符串,使用repr函数转换 |
%s | 字符串,使用str函数转换 |
%s | 字符 % |
In [13]: '%d' % 3.4 Out[13]: '3'
In [14]: '%E' % 0.00000000001 Out[14]: '1.000000E-11' In [15]: '%E' % 1000000000000 Out[15]: '1.000000E+12'
In [16]: '%g' % 0.001 Out[16]: '0.001' In [17]: '%g' % 0.00000001 Out[17]: '1e-08'
Flag | 说明 |
---|---|
# | #代表一个数字,指定宽度,如果宽度不够,会根据一下进行填充 |
0 | 使用0填充,仅适用于数字 |
. | 使用空格填充,默认为行 |
- | 右边使用空格填充 |
+ | 填充之前增加+,仅仅对于正数 |
In [20]: '%10d' % 1 Out[20]: ' 1' In [21]: '%010d' % 1 Out[21]: '0000000001'
template.format(*args, **kwargs) (1) (2) (3) (4)
template 使用{} 表示变量
{}或{\d+} 使用args 按顺序填充
{key} 使用*kwargs 按key填充
Format String Syntax
In [24]: '{0}, {name}'.format('Hello', name='World') Out[24]: 'Hello, World'
In [44]: '{server}{1}:{0}'.format(8888, '192.168.1.1', server='Web Server: ') Out[44]: 'Web Server: 192.168.1.1:8888'
In [45]: '{0}*{1}={2:<2}'.format(3,2,2*3) Out[45]: '3*2=6 ' In [46]: '{0}*{1}={2:<02}'.format(3,2,2*3) Out[46]: '3*2=60' In [47]: '{0}*{1}={2:>02}'.format(3,2,2*3) Out[47]: '3*2=06' In [48]: '{:^30}'.format('centered') Out[48]: ' centered ' In [49]: '{:*^30}'.format('centered') Out[49]: '***********centered***********'
In [50]: 'int:{0:d}; hex:{0:x}; oct:{0:o}; bin:{0:b}'.format(42) Out[50]: 'int:42; hex:2a; oct:52; bin:101010'
In [52]: '{:02X}{:02X}{:02X}{:02X}'.format(*[192,168,1,1]) Out[52]: 'C0A80101'
In [4]: s = 'Rick Xu {age} years old' In [5]: s.format_map({'age': 29}) Out[5]: 'Rick Xu 29 years old'
f ' <text> { <expression> <optional !s, !r, or !a> <optional : format specifier> } <text> ... '
>>> name = "Tom" >>> age = 3 >>> f"His name is {name}, he's {age} years old." >>> "His name is Tom, he's 3 years old."
# 数学运算 >>> f'He will be { age+1 } years old next year.' >>> 'He will be 4 years old next year.' # 对象操作 >>> spurs = {"Guard": "Parker", "Forward": "Duncan"} >>> f"The {len(spurs)} players are: {spurs['Guard']} the guard, and {spurs['Forward']} the forward." >>> 'The 2 players are: Parker the guard, and Duncan the forward.' >>> f'Numbers from 1-10 are {[_ for _ in range(1, 11)]}' >>> 'Numbers from 1-10 are [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]'
>>> def show_players(): print(f"{'Position':^10}{'Name':^10}") for player in spurs: print(f"{player:^10}{spurs[player]:^10}") >>> show_players() Position Name Guard Parker Forward Duncan
# 小数精度 >>> PI = 3.141592653 >>> f"Pi is {PI:.2f}" >>> 'Pi is 3.14' # 进制转换 >>> f'int: 31, hex: {31:x}, oct: {31:o}' 'int: 31, hex: 1f, oct: 37'
>>> fr'hello\nworld' 'hello\\nworld'
{}
内不能包含反斜杠\
f'His name is {\'Tom\'}' SyntaxError: f-string expression part cannot include a backslash # 而应该使用不同的引号,或使用三引号。 >>> f"His name is {'Tom'}" 'His name is Tom'
'u'
联合使用'u'
是为了与Python2.7兼容的,而Python2.7不会支持f-strings,因此与'u'
联合使用不会有任何效果。
>>> f"{{ {10 * 8} }}" '{ 80 }' >>> f"{{ 10 * 8 }}" '{ 10 * 8 }'
str.format()
的一点不同使用str.format()
,非数字索引将自动转化为字符串,而f-strings则不会。
>>> "Guard is {spurs[Guard]}".format(spurs=spurs) 'Guard is Parker' >>> f"Guard is {spurs[Guard]}" Traceback (most recent call last): File "<pyshell#34>", line 1, in <module> f"Guard is {spurs[Guard]}" NameError: name 'Guard' is not defined >>> f"Guard is {spurs['Guard']}" 'Guard is Parker'
将s中的元素,以str为分割符,合并成为一个字符串
In [26]: L Out[26]: ['I', 'love', 'Python'] In [27]: ''.join(L) Out[27]: 'IlovePython' In [28]: '_'.join(L) Out[28]: 'I_love_Python' In [30]: L Out[30]: ['I', 'love', 'Python'] In [31]: for i in L: ...: ret += i ...: ret += '' ...: ret ...: Out[31]: 'IlovePython'
In [27]: 'Hello' + 'World' Out[27]: 'HelloWorld'
sep 指分隔符,默认为空格
maxsplit 指分割次数, -1表示遍历整个字符串
split(sep=None, maxsplit=-1)
分割成列表
In [32]: s = 'I Love Python' In [33]: s.split() Out[33]: ['I', 'Love', 'Python'] In [34]: s.split('o') Out[34]: ['I L', 've Pyth', 'n'] In [37]: S Out[37]: 'root:*:0:0:System Administrator:/var/root:/bin/sh' In [38]: S.split(':') Out[38]: ['root', '*', '0', '0', 'System Administrator', '/var/root', '/bin/sh'] In [39]: S.split(':')[0] Out[39]: 'root' In [40]: username, _ = S.split(':', 1) In [41]: username Out[41]: 'root' In [42]: new_s = 'URL:http://xuxuehua.com' In [43]: k, v = new_s.split(':', 1) In [44]: k, v Out[44]: ('URL', 'http://xuxuehua.com')
In [80]: import re In [81]: s Out[81]: 'ab;cd|efg|hi,jkl|mn\topq;rst,uvw\txyz' In [82]: re.split(r'[,;\t|]+', s) Out[82]: ['ab', 'cd', 'efg', 'hi', 'jkl', 'mn', 'opq', 'rst', 'uvw', 'xyz']
rsplit(sep=None, maxsplit=-1)
sep 指分隔符,默认为空格
maxsplit 指分割次数, -1表示遍历整个字符串
In [45]: new_s Out[45]: 'URL:http://xuxuehua.com' In [46]: new_s.rsplit(':') Out[46]: ['URL', 'http', '//xuxuehua.com'] In [47]: new_s.rsplit(':', 1) Out[47]: ['URL:http', '//xuxuehua.com']
splitlines([keepends])
按照行来切分字符串
keepends表示是否保留行分隔符
行分隔符包括: \n, \r\n, \r 等
In [51]: s Out[51]: '\nI Love Python\n I love Linux either\n' In [52]: s.splitlines() Out[52]: ['', 'I Love Python', ' I love Linux either'] In [53]: s.splitlines(True) Out[53]: ['\n', 'I Love Python\n', ' I love Linux either\n'] In [54]: s.splitlines(False) Out[54]: ['', 'I Love Python', ' I love Linux either']
partition(sep) -> (head, sep, tail)
从左至右,遇到分隔符就把字符串分隔成: 头,分隔符,尾三元组
若没有分隔符,返回头和两个空元组
sep为分隔符,必须指定
In [58]: s Out[58]: 'root:*:0:0:System Administrator:/var/root:/bin/sh' In [59]: s.partition(':') Out[59]: ('root', ':', '*:0:0:System Administrator:/var/root:/bin/sh') In [60]: h, _, t = s.partition(':') In [61]: t Out[61]: '*:0:0:System Administrator:/var/root:/bin/sh' In [62]: h, _, t = t.partition(':') In [63]: t Out[63]: '0:0:System Administrator:/var/root:/bin/sh'
rpartition(sep) -> (head, sep, tail)
从右至左,遇到分隔符就把字符串分隔成: 头,分隔符,尾三元组
若没有分隔符,返回头和两个空元组
sep为分隔符,必须指定
In [64]: s Out[64]: 'root:*:0:0:System Administrator:/var/root:/bin/sh' In [65]: s.rpartition(':') Out[65]: ('root:*:0:0:System Administrator:/var/root', ':', '/bin/sh') In [66]: h, _, t = s.rpartition(':') In [67]: t Out[67]: '/bin/sh'
(字符串是不可修改的,这里是返回一个新的字符串)
replace(old, new[, count]) -> str
负数操作会替换所有
In [146]: s Out[146]: 'I love Python' In [147]: s.replace('o', 'x') Out[147]: 'I lxve Pythxn' In [148]: s.replace('o', 'x', 1) Out[148]: 'I lxve Python' In [149]: s.replace('o', 'x', -1) Out[149]: 'I lxve Pythxn'
In [2]: s Out[2]: 'I love Python' In [3]: s.replace('love', 'hate').replace('Python', 'C#') Out[3]: 'I hate C#'π
首单词的首字母大写
In [68]: s = 'i love python' In [69]: s.capitalize() Out[69]: 'I love python'
每个单词首字母大写
In [70]: s Out[70]: 'i love python' In [71]: s.title() Out[71]: 'I Love Python'
In [72]: s Out[72]: 'i love python' In [73]: s.upper() Out[73]: 'I LOVE PYTHON'
In [77]: S Out[77]: 'I love python' In [78]: S.lower() Out[78]: 'i love python'
互换大小写
In [82]: S Out[82]: 'I Love Python' In [83]: S.swapcase() Out[83]: 'i lOVE pYTHON'
center(width, [fillchar])
width 打印宽度
fillchar 填充字符
In [87]: s Out[87]: 'Python' In [88]: s.center(20) Out[88]: ' Python ' In [89]: s.center(20, '*') Out[89]: '*******Python*******'
ljust(width, [fillchar])
In [91]: s Out[91]: 'Python' In [92]: s.ljust(20) Out[92]: 'Python ' In [93]: s.ljust(20, '*') Out[93]: 'Python**************'
rjust(width, [fillchar])
In [96]: s Out[96]: 'Python' In [97]: s.rjust(20) Out[97]: ' Python' In [98]: s.rjust(20, '*') Out[98]: '**************Python'
zfill(width)
width 打印宽度,居右,左边用0填充
In [103]: s Out[103]: 'Python' In [104]: s.zfill(10) Out[104]: '0000Python' In [105]: s.zfill(11) Out[105]: '00000Python'
常用于处理文本, 去除空格和去掉首尾的str字符串换行符
strip([chars]) -> str
chars 不指定,默认为空白字符
In [25]: a = '\n abc \n' In [26]: a.strip() Out[26]: 'abc'
表示只去掉尾部的str字符串。
In [113]: s Out[113]: 'abc \n ' In [114]: s.rstrip() Out[114]: 'abc'
表示只去掉开头的str字符串
In [24]: a = '\n abc \n' In [25]: a.lstrip() Out[25]: 'abc \n'
In [1]: s = 'Rick \t Xu' In [2]: s.expandtabs(tabsize=20) Out[2]: 'Rick Xu'
In [41]: s Out[41]: 'this is Rick' In [42]: len(s) Out[42]: 12
In [124]: s Out[124]: 'I love Python' In [125]: s.startswith('I') Out[125]: True In [126]: s.startswith('l') Out[126]: False
In [127]: s Out[127]: 'I love Python' In [128]: s.endswith('n') Out[128]: True In [129]: s.endswith('o') Out[129]: False
count(sub[, start[, end]]) -> int
In [130]: s Out[130]: 'I love Python' In [131]: s.count('l') Out[131]: 1 In [132]: s.count('o') Out[132]: 2
index(sub[, start[, end]]) -> int
从左开始,查找sub在str中第一次出现的位置。如果str中不包含sub,出错
In [135]: s Out[135]: 'I love Python' In [136]: s.index('o') Out[136]: 3 In [145]: s.index('x') --------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-145-a677ba2c36a5> in <module>() ----> 1 s.index('x') ValueError: substring not found
rindex(sub[, start[, end]]) -> int
从右开始,查找sub在str中第一次出现的位置。如果str中不包含sub,返回 -1
In [137]: s Out[137]: 'I love Python' In [138]: s.rindex('o') Out[138]: 11
find(sub[, start[, end]]) -> int
从左开始,查找sub在str中第一次出现的位置。如果str中不包含sub,返回-1
In [139]: s Out[139]: 'I love Python' In [140]: s.find('l') Out[140]: 2 In [141]: s.find('o') Out[141]: 3 In [142]: s.find('Python') Out[142]: 7 In [143]: s.find('xuxu') Out[143]: -1
rfind(sub[, start[, end]]) -> int
从右开始,查找sub在str中第一次出现的位置。如果str中不包含sub,返回 -1
In [2]: s = 'I love Python' In [3]: s.rfind('I') Out[3]: 0 In [4]: s.rfind('o') Out[4]: 11 In [5]: s.rfind('xxh') Out[5]: -1
如果所有的字符都是字母或数字
In [6]: 'ab23'.isalnum() Out[6]: True
如果所有的字符都是字母
In [7]: 'abA'.isalpha() Out[7]: True
In [8]: '1A'.isdecimal() Out[8]: False
如果所有的字符都是数字
In [9]: '1A'.isdigit() Out[9]: False
In [10]: 'a1A'.isidentifier() Out[10]: True In [11]: '1A'.isidentifier() Out[11]: False
In [12]: '11A'.isnumeric() Out[12]: False
如果所有的词的首字母都是大写
In [13]: 'My name'.istitle() Out[13]: False In [14]: 'My Name'.istitle() Out[14]: True
如果所有的字符都是大写字母
In [15]: 'aA'.isupper() Out[15]: False
如果所有的字符都是小写字母
In [8]: s = 'abc' In [9]: s.islower() Out[9]: True
如果所有的字符都是空格
In [6]: s = " " In [7]: s.isspace() Out[7]: True
Python3 中严格区分了文本和二进制数据
Python2 中并没有严格区分
文本数据使用str类型,底层实现是unicode
二进制数据使用bytes类型,底层是bytes
str使用encode 方法转化为bytes
bytes使用decode方法转化为str
In [1]: s = '中文' In [2]: s Out[2]: '\xe4\xb8\xad\xe6\x96\x87' In [3]: s.encode() --------------------------------------------------------------------------- UnicodeDecodeError Traceback (most recent call last) <ipython-input-2-1194a7b23c15> in <module>() ----> 1 s.encode() UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
In [5]: s Out[5]: '中文' In [6]: s.encode() Out[6]: b'\xe4\xb8\xad\xe6\x96\x87' In [7]: s.encode('utf-8') Out[7]: b'\xe4\xb8\xad\xe6\x96\x87' In [8]: b = s.encode() In [9]: b.decode() Out[9]: '中文'
Starting in Python 2.6 you can use the built-in ast.literal_eval
:
>>> import ast >>> ast.literal_eval("{'muffin' : 'lolz', 'foo' : 'kitty'}") {'muffin': 'lolz', 'foo': 'kitty'}
This is safer than using eval
. As its own docs say:
>>> help(ast.literal_eval) Help on function literal_eval in module ast: literal_eval(node_or_string) Safely evaluate an expression node or a string containing a Python expression. The string or node provided may only consist of the following Python literal structures: strings, numbers, tuples, lists, dicts, booleans, and None.
For example:
>>> eval("shutil.rmtree('mongo')") Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1, in <module> File "/opt/Python-2.6.1/lib/python2.6/shutil.py", line 208, in rmtree onerror(os.listdir, path, sys.exc_info()) File "/opt/Python-2.6.1/lib/python2.6/shutil.py", line 206, in rmtree names = os.listdir(path) OSError: [Errno 2] No such file or directory: 'mongo' >>> ast.literal_eval("shutil.rmtree('mongo')") Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/opt/Python-2.6.1/lib/python2.6/ast.py", line 68, in literal_eval return _convert(node_or_string) File "/opt/Python-2.6.1/lib/python2.6/ast.py", line 67, in _convert raise ValueError('malformed string') ValueError: malformed string
s = '' for n in range(0, 100000): s += str(n)
l = [] for n in range(0, 100000): l.append(str(n)) s = ' '.join(l)
直观上看似乎第二种方法的复杂度高一倍,但实际运行了下,第二种方法效率略高,当调高到50万的时候第二种的效率比第一种高出两倍以上。
join的运行时间只占了很小一部分,不到10%,复杂度推测大致是O(logn)。综上,list的扩充速度优于str,且join的速度在大数面前可忽略。
推荐方法
s = " ".join(map(str, range(0, 10000)))