在 Python 中处理文本数据是使用 str 对象(文本序列类型),也称为字符串。字符串是由 Unicode 码位构成的不可变序列。字符串也可以通过使用 str 构造器从其他对象创建。
字符串字面值有如下几种写法:
单引号: ‘允许包含有 “双” 引号’
双引号: “允许包含有 ‘单’ 引号”。
三重引号: ‘’‘三重单引号’‘’, “”“三重双引号”“”
使用三重引号的字符串可以跨越多行,字符串中可以包含换行符、制表符以及其他特殊字符。 其中所有的空白字符都将包含在该字符串字面值中。
此外,作为单一表达式组成部分,由空格分隔的多个字符串字面值会被隐式地转换为单个字符串字面值。比如:("hello, " “world”) 转换为 “hello,world”。
通常来说,可使用print函数输出字符串:
>>>print("我是字符串")
我是字符串
一个转义字符创建一个字符序列,使得转义字符开头的该字符序列具有不同于该字符序列单独出现时的语义。python 用反斜杠 \ 开头表示转义字符,如下表所示:
转义字符 描述
(在行尾时) 续行符
\ 反斜杠符号
’ 单引号
" 双引号
\a 响铃
\b 退格(Backspace)
\e 转义
\000 空
\n 换行
\v 纵向制表符
\t 横向制表符
\r 回车
\f 换页
\oyy 八进制数,y 代表 0~7 的字符,例如:\012 代表换行。
\xyy 十六进制数,以 \x 开头,yy代表的字符,例如:\x0a代表换行
\other 其它的字符以普通格式输出
字符串内可包含转义字符,比如下面代码:
>>print("hello\nworld\t您好\t很高兴认识您")
hello
world 您好 很高兴认识您
上面代码在“hello”、“world”之间插入了转义字符‘\n’表示换行,在“world”、“您好”、“很高兴认识您”之间插入了转义字符’\t’表示tab。
如果将转义字符当作普通字符处理,可用 r (“raw”) 前缀来禁用大多数转义序列的处理,如下面代码所示:
print(r"hello\nworld\t 您好\t很高兴认识您")
hello\nworld\t 您好\t很高兴认识您
Python字符串可以嵌入变量、表达式的值,通常有以下2种方式:
1、字符串格式符 %s
这种方式使用历史悠久,从Python2时代就开始使用。
>>>name="zhangsang"
>>>age=28
>>>print("%s的年龄是:%s"%(name,age))
zhangsang的年龄是:28
%s相当于点位符的作用,帮要嵌入的值占一个位置,当程序实际运行时,再把嵌入的值替换%s。
2、f-strings
从Python 3.6开始,f-strings成为一种很好的格式化字符串的新方法,不仅可读性更好,更简洁,比其他格式更不容易出错,而且速度也更快。
使用 格式化字符串字面值 ,要在字符串开头的引号/三引号前添加 f 或 F 。在这种字符串中,可以在 { 和 } 字符之间输入引用的变量,或字面值的 Python 表达式。
>>>year=2021
>>>name="wangwu"
>>>print(f"{name}你好,今年是{year}年。")
wangwu你好,今年是2021年。
1、字符串乘法
用于完成重复输出字符串。
>>>print(5*"abc")
Abcabcabcabcabc
2、字符串加法
连接2个字符串。
>>>x="abcdef"
>>>y="efgh"
>>>x+y
'abcdefefgh'
3、字符串成员检测运算
运算符 in 和 not in 用于成员检测,在字符串中字符串a是字符串b的成员意味着,字符串b包含字符串a。
如果 x 是 s 的成员则 x in s 求值为 True,否则为 False。如果x不是s的成员,则x not in s 返回 True,否则返回False。所有内置序列和集合类型以及字典都支持此运算
>>>x="ab"
>>>y="abcdef"
>>>x in y
True
上述代码中,如果y中包含x则返回True,否则返回False。
4、接收字符串输入
使用input函数接收输入,输入类型为字符串型。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#2-5-1.py
import datetime
now=datetime.datetime.now()
name=input("输入名字:")
birthYear=input("您是哪一年出生的?")
age=now.year-int(birthYear)+1
print(f"{name},您今年虚岁:{age}")
上面程序首先使用datetime包中datetime类的now方法获得当前日期(datetime.datetime.now()),然后通过now.year取得当年年度,接着,计算虚岁,因为input输入的是字符串,所以需要通过int函数转换为整型(int(birthYear)),最后通过print函数向屏幕输出姓名和年龄。
程序运行结果如下:
输入名字:张三
您是哪一年出生的?1996
张三,您今年虚岁:26
序列有三种基本序列类型:list(列表), tuple(元组)和 range(不可变的数字序列),上一节讲解的字符串属于特别定制的附加序列类型。
列表是可变序列,通常用于存放同类元素(项目)的集合(但项目类型可以不同),列表既然是序列,那么其中的元素都是有前后顺序之分的。
>>>x2=['a','b','cd','ef','g']
>>>x1=[11,22,33,44,55,66]
>>>x1
[11, 22, 33, 44, 55, 66]
>>>x2
['a', 'b', 'cd', 'ef', 'g']
上述代码先定义了x2,存放的元素为字符串 ,再字义了x1,存放的元素是整数。
>>>z=[11,'qqq']
>>>z
[11, 'qqq']
上述代码定义了z,依次存放了整型和字符串2个元素。
列表还可包含子列表。如下面代码所示:
>>>x=['abc','def',123,456,'ABC']
>>>x
['abc', 'def', 123, 456, 'ABC']
>>>y=[11,x,22]
y
[11, ['abc', 'def', 123, 456, 'ABC'], 22]
>>>z=[10,20,[100,200],30]
>>>z
[10, 20, [100, 200], 30]
上面代码首先定义了列表x;然后将列表x作为列表y的元素(子列表),定义了有3个元素的列表y;最后,定义了列表z,列表z的索引为2的元素是子列表,值为[100,200]。
字符串和列表一样,也是序列,可通过list函数转换为列表,字符串里的每个字符成为列表的元素,
>>>s='hello,world'
>>>list(s)
['h', 'e', 'l', 'l', 'o', ',', 'w', 'o', 'r', 'l', 'd']
>>>s="你好,世界"
>>>list(s)
['你', '好', ',', '世', '界']
列表有以下常用操作:
1、索引方式
索引使用数字来指示元素位置,其格式如下:
列表名[索引位置]
(1)单元素索引
>>>x=[11,22,33]
>>x[1]
22
>>>x[0]
11
>>>x[2]
33
让初学者常感到疑惑的是:索引位置为1的元素(x[1])是22,为什么不是11呢,因为Python列表的索引是从0开始的,因此,x[0]才是11。
2、多元素(列表子集)索引
通过指示元素的起始位置来标注元素范围,其格式如下:
列表名[起始位置:终止位置(不包括终止位置本身)]
特别值得注意的是,其范围是从起始位置(包括起始位置)开始到终止位置(切记不包括终止位置)结束,也就是只到终止位置的前一个位置(包括终止位置前一个位置)。
>>>x=[1,2,3,4,5,6,7]
>>>x[0:3]
[1, 2, 3]
>>>x[4:6]
[5, 6]
上述代码中,x[0,3]表示从第0个位置到第3个位置结束,但不包括第3个位置。X[4:6]表示从第4个位置到第6个位置结束,但不包括第6个位置。还要注意一点:索引是从0开始的。
3、移除并提取(退栈)
s.pop([i])
当i为空时,表示直接从栈顶(将列表视为堆栈,列表的尾部为栈顶)弹出元素,否则提取在列表 i 位置上的项,并将其从 s 中移除。
>>>x=[1,2,3,4,5,6,7,8]
>>>x.pop()
8
>>>x
[1, 2, 3, 4, 5, 6, 7]
>>>x.pop(3)
4
>>>x
[1, 2, 3, 5, 6, 7]
上面代码,首先从栈顶弹出元素8,然后,再提取并移除列表的索引3位置的元素4。
提示:堆栈是允许在同一端进行插入和删除操作的特殊线性表。允许进行插入和删除操作的一端称为栈顶(top),另一端为栈底(bottom);栈底固定,而栈顶浮动;栈中元素个数为零时称为空栈。插入一般称为进栈(PUSH),删除则称为退栈(POP)
可通过索引方式直接修改列表中的单个元素或某些元素。
x=[1,2,3,4,5,6,7,8]
x
[1, 2, 3, 4, 5, 6, 7, 8]
x[4]=55
x
[1, 2, 3, 4, 55, 6, 7, 8]
x[5:7]=[66,77]
x
[1, 2, 3, 4, 55, 66, 77, 8]
上述代码先修改x的第4位元素(x[4]),将5改为55,然后再修改5~6位元素(x[5:7]),将6、7改为66、77。
对于子列表也可进行修改,如下代码所示:
>>>z=[10,20,[100,200],30]
>>>z
[10, 20, [100, 200], 30]
>>>z[0]=1000
>>>z
[1000, 20, [100, 200], 30]
>>>z[2]=[1,2]
>>>z
[1000, 20, [1, 2], 30]
>>>z[2]=[1,2,3,4,5,6]
>>>z
[1000, 20, [1, 2, 3, 4, 5, 6], 30]
>>>z[1:2]=[200,[11,22]]
>>>z
[1000, 200, [11, 22], [1, 2, 3, 4, 5, 6], 30]
上面代码首先定义列表z,该列表包括子列表元素;然后将z的第0个索引位置的元素改为1000,再将第2个索引位置的元素(有2个元素的子列表)改为[1,2];接着,第2个索引位置的元素(有1、2这2个元素的子列表)改为[1,2,3,4,5,6],这样,z的第2个索引位置的元素是一个有6个元素的子列表;最后,将z 的索引位置从1到2的元素,分别改为200和[11,22]。
1、append方法在列表末尾添加一个元素,调用格式如下:
list.append(x)
其中,list是列表,x是元素。
>>>x=[1,2,3]
>>>x.append(10)
>>>x
[1, 2, 3, 10]
>>>x.append(20)
>>>x
[1, 2, 3, 10, 20]
>>>y=[110,200]
>>>x.append(y)
>>>x
[1, 2, 3, 10, 20, [110, 200]]
上述代码中,首先,定义列表x,包括3个元素1、2、3;接着,列表x增加一个元素20,列表x现在共有5个元素:1、2、3、10、20;最后,定义了列表y(有110、120共2个元素),将列表y加入列表x中作为一个元素(y作为子列表)。
2、extend() 函数用于在列表末尾追加另一个序列中的多个值,通过添加iterable(可迭代的对象)中的所有项来扩展列表。调用格式如下:
list.extend (iterable)
>>> x=[1,2,3]
>>> y=[10,20,30]
>>> x.extend(y)
>>> x
[1, 2, 3, 10, 20, 30]
3、insert()函数在给定位置插入一项。调用格式如下:
list.insert(i, x)
在给定位置i插入一项x,第一个参数i是要插入的元素的索引,所以a.insert(0, x)插入到列表的前面,而a.insert(len(a), x)等价于a.append(x)。
>>>x=[1,2,3,4,5]
>>>x.insert(3,10)
>>>x
[1, 2, 3, 10, 4, 5]
>>>x.insert(0,20)
>>>x
[20, 1, 2, 3, 10, 4, 5]
>>>x.insert(3,[100,200])
>>>x
[20, 1, 2, [100, 200], 3, 10, 4, 5]
1、删除所有元素
clear()删除列表里的所有元素。调用格式如下:
list.clear()
>>>x=[1,2,3]
>>>x.clear()
>>>x
[]
2 .remove()删除指定元素。调用格式如下:
list.remove(x)
从列表中删除第一个值为 x 的元素。未找到指定元素时,触发 ValueError 异常。
>>>x=[10,20,30]
>>>x.remove(20)
>>>x
[10, 30]
>>>x.remove(20)
Traceback (most recent call last):
Python Shell, prompt 13, line 1
builtins.ValueError: list.remove(x): x not in list
3.pop()删除并返回列表中指定位置的元素。
list.pop([i])
删除列表中指定位置的元素,并返回被删除的元素。未指定位置(i是可选的)时,a.pop() 删除并返回列表的最后一个元素。
>>>x=[1,2,3,4,5,6]
>>>z=x.pop()
>>>z
6
>>>x
[1, 2, 3, 4, 5]
>>>y=x.pop(3)
>>>y
4
>>>x
[1, 2, 3, 5]
4.del()按索引,而不是值从列表中移除元素。与返回值的 pop() 方法不同, del 语句也可以从列表中移除切片,或清空整个列表。
>>>x=[1,2,3,4,5]
#移除元素
>>>del x[2]
>>>x
[1, 2, 4, 5]
#移除切片
>>>del x[1:3]
>>>x
[1, 5]
#清空整个列表
>>>del x[:]
>>>x
[]
此外,del 可删除整个变量。
>>>del x
>>>x
Traceback (most recent call last):
Python Shell, prompt 22, line 1
builtins.NameError: name 'x' is not defined
1、列表加法
前面已经讲述过,列表加法完成的功能是将2个列表合并为一个列表 。
>>>x1=[11,22,33]
>>>x2=[1,2,3]
>>>x1+x2
[11, 22, 33, 1, 2, 3]
2、列表推导式
列表推导式创建列表的方式更简洁。常见的用法为:对序列或可迭代对象中的每个元素应用某种操作,用生成的结果创建新的列表;或用满足特定条件的元素创建子序列。
例如,创建平方值的列表:
>>>squares = []
>>>for x in range(10):
... squares.append(x**2)
>>>squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
可以使用下面的列表推导式来完成上述代码的功能,简洁清晰。
>>>squares = [x**2 for x in range(10)]
3、列表算术运算法
(1)列表没有直接的算术加减法,但是可以通过列表推导式完成。下面代码完成将列表算术减法,即:相同位置的2个元素相减的功能。
>>>x1
[11, 22, 33]
>>>x2
[1, 2, 3]
>>>[x_1-x_2 for x_1,x_2 in zip(x1,x2)]
[10, 20, 30]
下面代码完成将列表算术加法,即:相同位置的2个元素相加的功能。
>>>x1
[11, 22, 33]
>>>x2
[1, 2, 3]
>>>[x_1+x_2 for x_1,x_2 in zip(x1,x2)]
[12, 24, 36]
(3)列表的算术乘除法
>>>x1
[11, 22, 33]
>>>x2
[1, 2, 3]
>>>[x_1*x_2 for x_1,x_2 in zip(x1,x2)]
[11, 44, 99]
>>>[x_1/x_2 for x_1,x_2 in zip(x1,x2)]
[11.0, 11.0, 11.0]
(4)列表乘法
列表的乘法“*”的功能是:列表的重复,而不是列表的算术乘法,其本质上就是将一个列表或者多个列表重复n次。
>>>x=[1,2,3]
>>>3*x
[1, 2, 3, 1, 2, 3, 1, 2, 3]
>>>x*2
[1, 2, 3, 1, 2, 3]
元组tuple是不可变序列,通常用于储存异构数据的多项集,也可用于创建同构数据的不可变序列的情况。创建元组的方式较多,有以下几种方式:
1、使用一对圆括号来表示空元组: ()。
2、使用内置的构造器创建元组,格式如下:
(1)tuple(iterable)
构造器将构造一个元组tuple,其中的项与 iterable(可迭代对象)中的项具有相同的值与顺序。 iterable 是序列、支持迭代的容器或其他可迭代对象。 如果 iterable 已经是一个元组,会原样返回,比如:
tuple(‘abc’) 返回 (‘a’, ‘b’, ‘c’) ,而 tuple( [1, 2, 3] ) 返回 (1, 2, 3)。
(2)tuple()
这种方式没有给出参数,构造器将创建一个空元组 ()。
3、使用一个后缀的逗号来表示单元组: a, 或 (a,)。
4、使用以逗号分隔的多个项: a, b, c 或(a, b, c)。
生成元组的关键在于逗号而不是圆括号,圆括号只是可选的。
但生成空元组或需要避免语法歧义的情况除外,例如:f(a, b, c) 是在调用函数时附带三个参数,而 f((a, b, c)) 则是在调用函数时附带一个三元组。
下面是示例代码:
#元组是只读的
>>>x=(10,20,30,40,50,60)
>>>x[3]=99
Traceback (most recent call last):
Python Shell, prompt 3, line 1
builtins.TypeError: 'tuple' object does not support item assignment
#空元组
>>>()
()
>>>tuple()
()
#以逗号分隔的多个项
>>>(1,2,3)
(1, 2, 3)
>>>1,5,8
(1, 5, 8)
#后缀逗号
>>>120,
(120,)
>>>(110,)
(110,)
#列表、元组(可迭代对象)的元素作为元组元素
>>>([1,2,3])
[1, 2, 3]
>>>((11,22))
(11, 22)
# 字符串(可迭代对象)作为元组构造器的参数
>>>tuple("abc")
('a', 'b', 'c')
2.5.4 字典
一、字典概述
字典(dict)是一种常用的 Python 內置数据类型。字典也是很多项的组合,不同之处在于,字典的每个项分为以下2部分内容:
1、键
一个键唯一标注了字典中的一项,字典中每一项的键都是独一无二的,前面讲述过列表的索引是以表示位置的数字标注的,而字典的索引可使用键来标注。
键是不可变的,它通常是字符串或数字,也可以是其他任意不可变类型。只包含字符串、数字、元组的元组,也可以用作关键字,如果元组直接或间接地包含了可变对象,就不能用作键。
2、值
不同项的值可以重复,每个键都对应一个值。
二、创建字典
字典创建的方式有以下2种:
1、花括号 {} 创建。
(1)空字典创建
>>>{}
{}
(2)初始化键值创建字典
>>>{'a':11,'b':12}
{'a': 11, 'b': 12}
2、使用构造器dict创建
(1)空字典创建
>>>dict()
{}
(2)初始化键值创建字典
>>>dict(a=11,b=12)
{'a': 11, 'b': 12}
>>>dict([('cc', 66), ('bb', 22), ('aa',11)])
{'cc': 66, 'bb': 22, 'aa': 11}
2、字典的主要操作
(1)存储值
可使用以下格式存储值:
字典变量名[键]=值
此外,用已存在的关键字存储值,与该关键字关联的旧值会被取代,完成更新的功能。
>>>x={}
>>>x['a']=11
>>>x['b']=12
>>>x
{'a': 11, 'b': 12}
>>>x['a']=10
>>>x
{'a': 10, 'b': 12}
(2)提取值
可使用以下格式提取某个键对应的值:
字典变量名[键]
>>>x={'a':11,'b':12,'c':13,'d':14}
>>>x
{'a': 11, 'b': 12, 'c': 13, 'd': 14}
>>>x['d']
14
>>>x['c']
13
此外,可通过迭代提取值,如下面几个代码所示:
使用keys方法提取所有键
>>>x=dict(d=1,e=2,a=10,b=20)
>>>x
{'d': 1, 'e': 2, 'a': 10, 'b': 20}
>>>for key in x.keys():
... print(x[key])
10
12
使用values方法提取所有值
>>>x=dict(d=1,e=2,a=10,b=20)
>>>x
{'d': 1, 'e': 2, 'a': 10, 'b': 20}
>>>for value in x.values():
... print(value)
10
12
>>>for key in x.keys():
... print(key,x[key])
a 10
b 12
用 items() 方法同时取出键和对应的值
>>>x=dict(d=1,e=2,a=10,b=20)
>>>x
{'d': 1, 'e': 2, 'a': 10, 'b': 20}
>>>for k,v in x.items():
... print(k,v)
d 1
e 2
a 10
b 20
(3)删除键值对
用 del 可以删除键值对。通过不存在的键提取值,则会报错。
>>>x
{'a': 10, 'b': 12}
>>>del x['a']
>>>x
{'b': 12}
(4)返回所有键的列表
对字典执行 list(d) 操作,返回该字典中所有键(按插入次序排列)的列表。
>>>x=dict(a=10,b=20)
>>>x
{'a': 10, 'b': 20}
>>>list(x)
['a', 'b']
请使用 sorted(d)对键进行排序。
>>x=dict(d=1,e=2,a=10,b=20)
>>>sorted(x)
[‘a’, ‘b’, ‘d’, ‘e’]
(5)检测键
检查字典里是否存在键,使用关键字 in。
>>>x=dict(d=1,e=2,a=10,b=20)
>>>'e' in x
True
>>>'ee' in x
False
(6)字典推导式
>>>{ k:2*k for k in ('a','b','c')}
{'a': 'aa', 'b': 'bb', 'c': 'cc'}
#range(10)的意思是产生0-9的数字
>>>{ k:2*k for k in range(10)}
{0: 0, 1: 2, 2: 4, 3: 6, 4: 8, 5: 10, 6: 12, 7: 14, 8: 16, 9: 18}
堆栈是一个特定的存储区或寄存器,它的一端是固定的(称栈底),另一端是浮动的(称栈顶) 。在堆栈存储区存入的数据,是一种特殊的数据结构,所有的数据存入或取出,只能在浮动的一端进行,严格按照“先进后出”的原则存取,位于其中间的元素,必须在其栈上部(后进栈者)的所有元素逐个移出后才能取出。
2-5-5.py用列表实现一个堆栈及相关操作。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#2-5-5.py
def printStack(stackData):
print("-----")
for data in stackData:
print(data)
print("-----")
stack=[]
stack.append(1)
printStack(stack)
stack.append(2)
printStack(stack)
stack.append(3)
printStack(stack)
data=stack.pop()
print(f"pop:{data}")
printStack(stack)
data=stack.pop()
print(f"pop:{data}")
printStack(stack)
2-5-5.py运行结果如下:
-----
1
-----
-----
1
2
-----
-----
1
2
3
-----
pop:3
-----
1
2
-----
pop:2
-----
1
-----
分析2-5-5.py及其运行结果。
1、定义printStack函数,2-5-5.py利用列表来保存堆栈内容,其功能是输出堆栈内容,按从栈底到栈顶的顺序输出。
(1)构建for循环。
(2)在for循环内逐个元素输出列表内容。
2、stack保存堆栈内容,其实质是一个列表。
3、在栈顶依次放入3个元素:1、2、3,每放入1个元素,就调用printStack输出当前栈内容。
stack.append(1)
printStack(stack)
stack.append(2)
printStack(stack)
stack.append(3)
printStack(stack)
4、从堆栈中依次取出3个元素:3、2、1,每取出1个元素,就调用printStack输出当前栈内容。
data=stack.pop()
print(f"pop:{data}")
printStack(stack)
data=stack.pop()
print(f"pop:{data}")
printStack(stack)
队列是一种特殊的线性表,和栈一样,队列是一种操作受限制的线性表,它只允许在表的前端进行删除操作,而在表的后端进行插入操作,在队列中插入一个队列元素称为入队,进行插入操作的端称为队尾,从队列中删除一个队列元素称为出队,进行删除操作的端称为队头。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出线性表。
模块collections的deque对象用于返回一个新的双向队列对象,用方法 append从左到右初始化 ,deque队列是由栈或者queue队列生成,deque 支持线程安全,从内存高效添加(append)和弹出(pop)。2-5-6.py实现队列的存取操作。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#2-5-6.py
from collections import deque
queue = deque([])
queue.append(1)
queue.append(2)
print(queue.popleft())
queue.append(3)
print(queue.popleft())
queue.append(4)
queue.append(5)
print(queue.popleft())
print(queue)
for data in queue:
print(data)
2-5-6.py运行结果如下:
1
2
3
deque([4, 5])
4
5
分析2-5-6.py文件如下:
1、导入deque对象,并定义空队列对象。
from collections import deque
queue = deque([])
2、在队列中放入元素:1、2,入队。
queue.append(1)
queue.append(2)
3、输出队头元素,出队。
print(queue.popleft())
其中,queue.popleft()表示从队列左边取出并删除1个元素,完成了出队操作,并返回队头元素1。
4、入队3,队头元素2出队并输出。
queue.append(3)
print(queue.popleft())
5、入队4、5,队头元素3出队并输出。
queue.append(4)
queue.append(5)
print(queue.popleft())
5、输出当前队列所有元素。
print(queue)
6、将队列所有元素逐个输出,此时队列还余下元素4、5。
for data in queue:
print(data)