3.1 字符串基础
字符串是python中常见的数据类型,如日志的打印,程序中函数的注释,数据库的访问,变量的基本操作等等,都用到了字符串。
字符串是由独立字符组成的一个序列,通常包含在单引号(’’)双引号("")或者三引号之中,需要注意的就是引号间的匹配和冲突问题:
"I'm a student"
python的三引号字符串,则主要用于多行字符串的情景,比如函数的注释等:
def calculate_similarity(item1, item2):
"""
Calculate similarity between two items
Args:
item1: 1st item
item2: 2nd item
Returns:
similarity score between item1 and item2
"""
python的常见转义字符:
以下面的代码为例:
s = 'a\nb\tc'
print(s)
================
a
b c
虽然s的打印输出横跨两行,但是整个字符串s依旧只有5个元素
len(s)
=============
5
python最常用的转义字符是‘\n’,如逐行读取某个文件,则每一行字符的末尾都会包含‘\n’,而最后做数据处理时,我们往往会丢掉最后的换行符
3.2 字符串的常用操作
字符串可以看做是由一些单个字符组成的数组,故同样可以执行索引、切片和遍历等操作。
字符串的常用操作和内置函数有很多,这里只讲了一些。
字符串修改
要特别注意的是,字符串是不可变的(immutable),因此,不能直接按下面的方式修改字符串:
s = 'hello'
s[0] = 'H'
===================================
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
python中字符串的修改,通常只能通过创建新字符串来完成(同Java),如要将字符串s=‘hello’修改为’Hello’,可用下面两种不同的方法:
1. s = 'H' + s[1:] #对原字符串进行切片操作
2. s = s.replace('h', 'H') #使用字符串的内置函数replace()
对于Java,我们可以使用可变的字符串类型如StringBuilder,每次增删改无需创建新的字符串,时间复杂度为O(1)。这样大大提高了程序运行的效率。
那么,是否python的字符串每次更改都需要新建字符串呢?答案是否定的。
字符串连接
使用“+=”进行字符串的拼接方法是一个例外,它打破了字符串不可变的特性。
s = ''
for n in range(0, 100000):
s += str(n)
上面的代码的时间复杂度是O(n),而不是O(n^2),因为使用“+=”的字符串拼接操作为O(1)
另外,对于字符串的拼接问题,还可以用字符串内置的join函数。
string.join(iterable),表示把每个元素都按照指定的格式连接起来
l = []
for n in range(0, 100000):
l.append(str(n))
l = ' '.join(l)
字符串分割
字符串分割常用其内置函数split()。string.split(sparator)指把string以sparator为截断点将其划分为各个部分并存储在列表里。
string.split(sparator)常常用于对数据的解析处理。如我们读取了某个文件的路径,想要调用数据库的API去读取数据库的数据,我们常常会这样写:
def query_data(namespace, table):
"""
given namespace and table, query database to get corresponding
data
"""
path = 'hive://ads/training_table'
namespace = path.split('//')[1].split('/')[0] # 返回'ads'
table = path.split('//')[1].split('/')[1] # 返回 'training_table'
data = query_data(namespace, table)
字符串去除左右指定字符
- string.lstrip(str):去掉开头的str字符串
- string.rstrip(str):去掉结尾的str字符串
- string.strip(str):去掉两边的str字符串
如读进来的字符串首尾有空格,想要去除掉:
s = ' my name is jason '
s.strip()
'my name is jason'
字符串查找子串位置:
string.find(sub, start, end):表示从 start 到 end 查找字符串中子字符串 sub的位置
3.3 字符串的格式化
字符串的格式化通常会用在程序输出、logging等场景。一个常见的例子是:有一个任务,给定一个用户的userid,要去数据库查询该用户的一些信息,并返回。若数据库中没有该用户的信息,我们通常会记录下来,这样有利于往后的日志分析,或者线上bug的调试等
这里主要记录两种格式化函数:string.format()和f"string":
- string.format()是以前python最常用的格式化函数,string里面的大括号{}是给format()里面传递的真值预留位置
print('no data available for person with id: {}, name: {}'.format(id, name))
=================================
'no data available for person with id: 123, name: jason'
- f-"string"是最新的也更高效的格式化方法。f-string 格式化就是在字符串模板前面加上f,然后占位符使用{} ,里面直接放入对应的变量
这里着重讲一下f-string的常用操作:
- f-string格式化
id = 123
name = jason
print(f"no data available for person with id: {id}, name: {name}")
- 指定输出字符的长度:为了输出对齐,我们通常需要指定输出的字符串的长度。
右对齐:直接在传入的变量后面加上 :length即可。这样,若字符串本身长度不足时,则会在输出字符串开头加上若干个空格补足到指定长度
def calcTax(salary):
tax = int(salary) *25/100
aftertax = int(salary) *75/100
print(f'税前薪资是:{salary:8}元, 缴税:{tax:8}元, 税后薪资是:{aftertax:8}元')
calcTax(8000)
calcTax(15000)
calcTax(100000)
输出:
左对齐:使用"<"符号
def calcTax(salary):
tax = int(salary) *25/100
aftertax = int(salary) *75/100
print(f'税前薪资是:{salary:<8}元, 缴税:{tax:<8}元, 税后薪资是:{aftertax:<8}元')
for n in [8000,15000,10000]:
calcTax(n)
输出:
-
小数点后位数
若要指定输出小数点后面的位数,直接在括号里:后使用.nf即可。
例如:{salary:.1f},{salary:8.1f},{salary:<8.1f} -
不足补零
在括号里:后的指定长度数前直接加0即可
例如:{salary:08.1f}
除了使用格式化函数之外,我们还可以像C语言一样使用%通配符,不过不推荐。使用格式化函数会使得程序更清晰易读,规范不易出错
如果字符串拼接的次数较少,比如range(100),那么方法一更优,因为时间复杂度精确的来说第一种是O(n),第二种是O(2n),如果拼接的次数较多,比如range(1000000),方法二稍快一些,虽然方法二会遍历两次,但是join的速度其实很快,列表append和join的开销要比字符串+=小一些
对于方法二,可以有更高效更pythonic的写法,即利用map(func,iterable)函数:
s =''.join(map(str,range(0, 100000)))