Python | 深入浅出字符串

本文授权转自极客时间专栏:(Python核心技术与实战)


640?wx_fmt=png

(2 天倒计时!扫码购买加微信返现 18 元)


Python的程序中充满了字符串(string),在平常阅读代码时也屡见不鲜。字符串同样是Python中很常见的一种数据类型,比如日志的打印、程序中函数的注释、数据库的访问、变量的基本操作等等,都用到了字符串。


当然,我相信你本身对字符串已经有所了解。今天这节课,我主要带你回顾一下字符串的常用操作,并对其中的一些小tricks详细地加以解释。


字符串基础

什么是字符串呢?字符串是由独立字符组成的一个序列,通常包含在单引号('')双引号("")或者三引号之中(''' '''或""" """,两者一样),比如下面几种写法。


 
 
name = 'jason'city = 'beijing'text = "welcome to jike shijian"'jason'
city = 'beijing'
text = "welcome to jike shijian"


这里定义了name、city和text三个变量,都是字符串类型。我们知道,Python中单引号、双引号和三引号的字符串是一模一样的,没有区别,比如下面这个例子中的s1、s2、s3完全一样。


 
 
s1 = 'hello's2 = "hello"s3 = """hello"""s1 == s2 == s3True
s2 = "hello"
s3 = """hello"""
s1 == s2 == s3
True


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    """
    """
    Calculate similarity between two items
    Args:
        item1: 1st item
        item2: 2nd item
    Returns:
      similarity score between item1 and item2
    """


同时,Python也支持转义字符。所谓的转义字符,就是用反斜杠开头的字符串,来表示一些特定意义的字符。我把常见的的转义字符,总结成了下面这张表格。


640?wx_fmt=png      

为了方便你理解,我举一个例子来说明。


 
 
s = 'a\nb\tc'print(s)ab    c
print(s)
a
b    c


这段代码中的'\n',表示一个字符——换行符;'\t'也表示一个字符——横向制表符。所以,最后打印出来的输出,就是字符a,换行,字符b,然后制表符,最后打印字符c。不过要注意,虽然最后打印的输出横跨了两行,但是整个字符串s仍然只有5个元素。


 
 
len(s)5
5


在转义字符的应用中,最常见的就是换行符'\n'的使用。比如文件读取,如果我们一行行地读取,那么每一行字符串的末尾,都会包含换行符'\n'。而最后做数据处理时,我们往往会丢掉每一行的换行符。


字符串的常用操作

讲完了字符串的基本原理,下面我们一起来看看字符串的常用操作。你可以把字符串想象成一个由单个字符组成的数组,所以,Python的字符串同样支持索引,切片和遍历等等操作。


 
 
name = 'jason'name[0]'j'name[1:3]'as''jason'
name[0]
'j'
name[1:3]
'as'


和其他数据结构,如列表、元组一样,字符串的索引同样从0开始,index=0表示第一个元素(字符),[index:index+2]则表示第index个元素到index+1个元素组成的子字符串。


遍历字符串同样很简单,相当于遍历字符串中的每个字符。


 
 
for char in name:    print(char)   jasonchar in name:
    print(char)   
j
a
s
o
n


特别要注意,Python的字符串是不可变的(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
Traceback (most recent call last):
  File "<stdin>", line 1in <module>
TypeError: 'str' object does not support item assignment


Python中字符串的改变,通常只能通过创建新的字符串来完成。比如上述例子中,想把'hello'的第一个字符'h',改为大写的'H',我们可以采用下面的做法:


 
 
s = 'H' + s[1:]s = s.replace('h', 'H')'H' + s[1:]
s = s.replace('h''H')


  • 第一种方法,是直接用大写的'H',通过加号'+'操作符,与原字符串切片操作的子字符串拼接而成新的字符串。


  • 第二种方法,是直接扫描原字符串,把小写的'h'替换成大写的'H',得到新的字符串。


你可能了解到,在其他语言中,如Java,有可变的字符串类型,比如StringBuilder,每次添加、改变或删除字符(串),无需创建新的字符串,时间复杂度仅为O(1)。这样就大大提高了程序的运行效率。


但可惜的是,Python中并没有相关的数据类型,我们还是得老老实实创建新的字符串。因此,每次想要改变字符串,往往需要O(n)的时间复杂度,其中,n为新字符串的长度。


你可能注意到了,上述例子的说明中,我用的是“往往”、“通常”这样的字眼,并没有说“一定”。这是为什么呢?显然,随着版本的更新,Python也越来越聪明,性能优化得越来越好了。


这里,我着重讲解一下,使用加法操作符'+='的字符串拼接方法。因为它是一个例外,打破了字符串不可变的特性。


操作方法如下所示:


 
 
str1 += str2  # 表示str1 = str1 + str2


我们来看下面这个例子:


 
 
s = ''for n in range(0, 100000):    s += str(n)
for n in range(0100000):
    s +
= str(n)


你觉得这个例子的时间复杂度是多少呢?


每次循环,似乎都得创建一个新的字符串;而每次创建一个新的字符串,都需要O(n)的时间复杂度。因此,总的时间复杂度就为O(1) + O(2) + ... + O(n) = O(n^2)。这样到底对不对呢?


乍一看,这样分析确实很有道理,但是必须说明,这个结论只适用于老版本的Python了。自从Python2.5开始,每次处理字符串的拼接操作时(str1 += str2),Python首先会检测str1还有没有其他的引用。如果没有的话,就会尝试原地扩充字符串buffer的大小,而不是重新分配一块内存来创建新的字符串并拷贝。这样的话,上述例子中的时间复杂度就仅为O(n)了。


因此,以后你在写程序遇到字符串拼接时,如果使用'+='更方便,就放心地去用吧,不用过分担心效率问题了。


另外,对于字符串拼接问题,除了使用加法操作符,我们还可以使用字符串内置的join函数。string.join(iterable),表示把每个元素都按照指定的格式连接起来。


 
 
l = []for n in range(0, 100000):    l.append(str(n))l = ' '.join(l) for n in range(0100000):
    l.append(str(n))
' '.join(l) 


由于列表的append操作是O(1)复杂度,字符串同理。因此,这个含有for循环例子的时间复杂度为n*O(1)=O(n)。


接下来,我们看一下字符串的分割函数split()。string.split(separator),表示把字符串按照separator分割成子字符串,并返回一个分割后子字符串组合的列表。它常常应用于对数据的解析处理,比如我们读取了某个文件的路径,想要调用数据库的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) 
    """
    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.strip(str),表示去掉首尾的str字符串;

  • string.lstrip(str),表示只去掉开头的str字符串;

  • string.rstrip(str),表示只去掉尾部的str字符串。


这些在数据的解析处理中同样很常见。比如很多时候,从文件读进来的字符串中,开头和结尾都含有空字符,我们需要去掉它们,就可以用strip()函数:


 
 
s = ' my name is jason 's.strip()'my name is jason'' my name is jason '
s.strip()
'my name is jason'


当然,Python中字符串还有很多常用操作,比如,string.find(sub, start, end),表示从start到end查找字符串中子字符串sub的位置等等。这里,我只强调了最常用并且容易出错的几个函数,其他内容你可以自行查找相应的文档、范例加以了解,我就不一一赘述了。


字符串的格式化

最后,我们一起来看看字符串的格式化。什么是字符串的格式化呢?


通常,我们使用一个字符串作为模板,模板中会有格式符。这些格式符为后续真实值预留位置,以呈现出真实值应该呈现的格式。字符串的格式化,通常会用在程序的输出、logging等场景。


举一个常见的例子。比如我们有一个任务,给定一个用户的userid,要去数据库中查询该用户的一些信息,并返回。而如果数据库中没有此人的信息,我们通常会记录下来,这样有利于往后的日志分析,或者是线上bug的调试等等。


我们通常会用下面的方法来表示:


 
 
print('no data available for person with id: {}, name: {}'.format(id, name))'no data available for person with id: {}, name: {}'.format(id, name))


其中的string.format(),就是所谓的格式化函数;而大括号{}就是所谓的格式符,用来为后面的真实值——变量name预留位置。如果id = '123'、name='jason',那么输出便是:


 
 
'no data available for person with id: 123, name: jason'


这样看来,是不是非常简单呢?


不过要注意,string.format()是最新的字符串格式函数与规范。自然,我们还有其他的表示方法,比如在Python之前版本中,字符串格式化通常用%来表示,那么上述的例子,就可以写成下面这样:


 
 
print('no data available for person with id: %s, name: %s' % (id, name))'no data available for person with id: %s, name: %s' % (id, name))


其中%s表示字符串型,%d表示整型等等,这些属于常识,你应该都了解。


当然,现在你写程序时,我还是推荐使用format函数,毕竟这是最新规范,也是官方文档推荐的规范。


也许有人会问,为什么非要使用格式化函数,上述例子用字符串的拼接不也能完成吗?没错,在很多情况下,字符串拼接确实能满足格式化函数的需求。但是使用格式化函数,更加清晰、易读,并且更加规范,不易出错。


总结

这节课,我们主要学习了Python字符串的一些基本知识和常用操作,并且结合具体的例子与场景加以说明,特别需要注意下面几点。


  • Python中字符串使用单引号、双引号或三引号表示,三者意义相同,并没有什么区别。其中,三引号的字符串通常用在多行字符串的场景。

  • Python中字符串是不可变的(前面所讲的新版本Python中拼接操作'+='是个例外)。因此,随意改变字符串中字符的值,是不被允许的。

  • Python新版本(2.5+)中,字符串的拼接变得比以前高效了许多,你可以放心使用。

  • Python中字符串的格式化(string.format)常常用在输出、日志的记录等场景。


思考题

最后,给你留一道思考题。在新版本的Python(2.5+)中,下面的两个字符串拼接操作,你觉得哪个更优呢?欢迎留言和我分享你的观点,也欢迎你把这篇文章分享给你的同事、朋友。


 
 
s = ''for n in range(0, 100000):    s += str(n)l = []for n in range(0, 100000):    l.append(str(n))s = ' '.join(l)
for n in range(0100000):
    s +
= str(n)


l = []
for n in range(0100000):
    l.append(str(n))

' '.join(l)


640?wx_fmt=png

(2 天倒计时!扫码购买加微信返现 18 元)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《深入浅出Python》是一本以简明易懂的方式介绍Python编程语言的中文版书籍。本书的目标是帮助读者快速入门Python,并且能够深入了解该语言的核心概念和使用技巧。 本书的第一部分首先介绍了Python语言的基础知识,包括Python的安装、简单的程序结构、变量、数据类型、运算符等。读者可以通过简单的示例代码来理解这些概念,并且掌握基本的编程技巧。 第二部分着重介绍Python的高级特性,如控制流、迭代器和生成器、函数和模块、文件操作等。通过详细的示例代码和解释,读者能够深入理解这些特性的使用方法,并掌握如何在自己的项目中应用它们。 在第三部分中,本书讨论了Python的面向对象编程。通过介绍类、继承、多态等概念,读者可以学习如何使用Python创建和管理对象,并且了解面向对象编程的优势和应用场景。 此外,本书还介绍了Python的常用标准库和第三方库,如字符串处理、日期和时间处理、数据库操作、网络编程等。读者可以学习如何使用这些库来提高自己的编程效率,并且了解Python在不同领域的应用场景。 总的来说,《深入浅出Python》中文版是一本适合初学者入门的Python编程书籍。通过简单易懂的讲解和丰富的示例代码,读者可以快速掌握Python的基本知识和应用技巧,并且为进一步学习和应用Python打下坚实的基础。 ### 回答2: 《深入浅出Python中文版》是一本面向初学者的Python编程入门书籍。这本书以简洁明了的语言和实例讲解了Python的基础知识和编程技巧。 首先,这本书详细介绍了Python的基本语法和语义,包括变量、数据类型、控制流语句等。读者可以通过学习这些内容来熟悉Python的基本编程概念,并快速上手写出简单的程序。 其次,本书还介绍了Python的面向对象编程(OOP)特性。通过讲解类、对象、继承等概念,读者可以学会如何使用Python进行面向对象的编程。而且,书中还有很多实例和练习题可以帮助读者巩固所学内容。 此外,本书还介绍了Python的常用标准库和第三方库,如字符串处理、操作文件、网络编程、数据可视化等。通过学习这些库的使用,读者可以更高效地完成各类任务,并提升自己的编程能力。 在阅读过程中,作者还提供了很多实用的技巧和最佳实践,帮助读者写出更加规范和高效的Python代码。此外,书中还有一些常见问题和解决方案,方便读者在遇到问题时能够迅速找到解决方法。 总之,《深入浅出Python中文版》是一本适合初学者的Python编程入门书籍。无论是对于那些没有编程经验的读者,还是对于有其他编程语言经验的读者,这本书都能够帮助他们快速入门Python,并具备一定的编程技能。 ### 回答3: 《深入浅出Python(中文版)》是一本极富教育性的Python编程入门书籍。这本书的目标是帮助读者全面了解Python编程语言,并帮助他们在实践中获得提高。下面是该书的主要内容和特点。 首先,该书注重深入浅出的教学风格。作者使用简单明了的语言和实例,解释了Python的基本概念和语法。这使得即使是没有编程经验的读者也能够轻松理解Python的核心概念。 其次,该书全面介绍了Python的各个方面。作者从Python的安装和配置开始,然后逐步介绍了变量、数据类型、控制流、函数、文件操作、异常处理等基本概念和技巧。此外,该书还涵盖了Python的面向对象编程、模块和包管理、文件读写、网络编程、数据库连接等进阶主题,让读者能够全面掌握Python的各个方面。 另外,该书还包含了大量的实例和练习。通过实例和练习,读者可以巩固所学知识,并将其应用于实际问题的解决中。这不仅提高了读者的编程能力,还激发了他们对编程的兴趣和创造力。 最后,该书强调了Python在数据科学和人工智能领域的应用。作者详细介绍了Python在数据处理、机器学习、深度学习等领域的应用,帮助读者了解如何使用Python进行数据分析和模型构建。 总之,《深入浅出Python(中文版)》是一本很好的Python入门书籍。无论是初学者还是有一定编程经验的人都能从中受益。它以简洁明了的语言和实例,全面深入地介绍了Python的各个方面,帮助读者建立起扎实的编程基础,并引领他们进入Python在数据科学和人工智能领域的精彩世界。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值