# 数据结构

# 字符串

把单个或多个字符用单引号或者双引号包围起来,就可以表示一个字符串。字符串中的转义使用\,也就是说\后面的字符不再是它原来的意思。

\n 表示换行符,\t 表示制表符,如果要在字符串中表示 \,就要写成 \\,如果表示 ',就要写成 \'

当然如果不需要转义的话,可以在字符串前面加上字母r来加以说明。

s1 = '\'hello world\''
s2 = '\n\\hello,world!\\\n'
print(s1,s2,end='')


s1 = '\'hello world\''
s2 = r'\n\\hello,world!\\\n'
print(s1,s2,end='')

# 字符串的运算符

s1 = 'hello'
s2 = 'world'

s3 = s1 + s2

s4 = s1 * 3

s5 = s1 in s3

s6 = s1 not in s3

print(s1,s2,s3,s4,s5,s6,end='')

字符串的切片是一种提取字符串中部分字串的强大方法,基本语法是使用方括号[]并指定开始索引(包含),结束索引(不包含)和可选的步长。

str[start:stop:step]

使用用样例如下:

s = "Hello, World!"  

# 提取从索引0到5的字符(不包含索引5)
print(s[0:5])   # 输出:Hello

# 省略开始索引,默认从0开始
print(s[:5])    # 输出:Hello

# 省略结束索引,默认到字符串末尾  
print(s[7:])   # 输出: World!  

# 同时省略开始和结束索引,提取整个字符串  
print(s[:])    # 输出: Hello, World! 

# 使用步长为2进行切片
print(s[::2])  # 输出: He,Wrd! 

# 使用负步长从后往前切片  
print(s[::-1]) # 输出: !dlroW ,olleH  

当然,字符串拥有很多内置函数,可以使用 help() 函数来查看 str 类型的详细信息,包含构造函数和所有可用的方法。

# 查看字符串对象的
help(str)

# 如果查看某个特定的字符串方法注意是引用,而不是调用
help(str.upper)

# 字符串的其他常用方法

下面列举一下常用的字符串函数:


s = 'hello world 222 你好啊 hello'

# 返回字符串的长度
str_length = len(s) 

# 字符串首字母大写
str_capitalize = s.capitalize() 

# 将字符串转换为小写
casefold = s.casefold() 

# 字符串每个单词首字母大写
str_title = s.title() 

# 将字符串转换为大写
str_upper = s.upper() 

# 将字符串转换为小写
str_lower = str_upper.lower() 

# 返回子字符串在字符串中首次出现的索引,如果没有找到则返回 -1
index = s.find('ll') 
index = s.find('shift')

# 与 find 类似,,但是如果没有找到子字符串,则会引发 ValueError 异常
str_index = s.index('ll') 
str_index = s.index('shift')

# 检查字符串是否以指定的字符串开头
start_with = s.startswith('a') 

# 检查字符串是否以指定的后缀结束
ends_with = s.endswith('.txt') 

# 返回一个居中的字符串,两边用指定的字符(默认为空格)填充至指定宽度
str_center = s.center(30,'*') 

# 返回子字符串在字符串中出现的次数,可以指定搜索的起始和结束位置
str_count = s.count('hello') 

# 将字符串以指定的编码格式编码,并返回编码后的字节串,默认使用 UTF-8 编码
str_encode = s.encode() 

s = 'AB 你好啊'

 # 检查字符串是否只包含字母和数字字符
str_isalnum = s.isalnum() # False

# 检查字符串是否只包含字母字符
str_isalpha = s.isalpha() # False

 # 检查字符串是否只包含数字字符,如果你只关心 ASCII 数字(0-9),那么使用 isdigit() 就足够了。
str_isdigit = s.isdigit() # False

# 检查字符串是否只包含数字字符,如果你需要处理更广泛的 Unicode 数字表示(如罗马数字、分数等),那么应该使用 isnumeric()。
str_isnumeric = s.isnumeric() # False

# 检查字符串中的所有字符是否都是小写
str_islower = s.islower()  # False

# 检查字符串中的所有字符是否都是大写
str_isupper = s.isupper() # TRUE

# 使用指定的字符串作为分隔符,将可迭代对象中的元素连接成一个新的字符串
s = '-'
s1 = s.join(['hello','world']) # 输出: "hello-world"

s = 'hello world'

# 返回一个左对齐的字符串,右边用指定的字符(默认为空格)填充至指定宽度
str_ljust = s.ljust(30,'#')

# 从字符串的左侧删除指定的字符(默认为空格)
str_lstrip = s.lstrip('#')

s = 'a-b-a-n-d-o-n'

# 根据指定的分隔符将字符串划分为三个部分,返回一个包含这三个部分的元组
str_partition = s.partition('-') # ('a', '-', 'b-a-n-d-o-n')

# 字符串的格式化操作

  • 使用 % 运算符(旧式格式化)
name = "Alice"  
age = 30  
print("My name is %s and I'm %d years old." % (name, age))
  • 使用 str.format() 方法(新式格式化)
name = "Alice"  
age = 30  

print("My name is {} and I'm {} years old.".format(name, age))

print("My name is {name} and I'm {age} years old.".format(name=name, age=age))


  • 使用 f-string(字面量格式化字符串,Python 3.6+)
name = "Alice"  
age = 30  
print(f"My name is {name} and I'm {age} years old.")
  • 使用 template 模块(模版字符串)

template 模块提供了一个简单的字符串替换机制,使用 $ 符号来标记变量。这种方法通常用于更复杂的字符串替换场景,如模板引擎。

from string import Template  

s = Template('Hello, $name! You are $age years old.')  
name = "Alice"  
age = 30  
print(s.substitute(name=name, age=age))
  • 使用第三方库

除了 Python 内置的字符串格式化方法外,还有一些第三方库提供了更强大和灵活的字符串格式化功能,如 jinja2(用于模板渲染)和 Pygments(用于语法高亮)。

# 列表(list)

定义列表可以将列表的元素放在 [] 中,多个元素用 , 分割。列表可以当做栈来使用,后进先出。当然也可以用队列,先进先出。然而列表做为队列的效率很低,因为在开头添加或移除元素时,其他元素都要必须移动一位。还可以当做列表推导式。

列表推导式的方括号内包含以下内容:一个表达式,后面为一个 for 子句,然后,是零个或多个 for 或 if 子句。结果是由表达式依据 for 和 if 子句求值计算而得出一个新列表。

一些基本用法,列表是可变的,可以添加元素(append,insert,extend等),删除元素(remove,pop,del),修改元素


list1 = [1,2,3]
list2 = [3,4,5]

# 计算列表的长度
list_len = len(list1)

list3 = list1 * 2

list4 = list1 + list2

# 判断在不在列表里
in_list = 6 in list1
in_list = 6 not in list1


# 按索引取某一值
a = list1[0]
b = list1[-1]

# 遍历列表打印值
for x in range(list_len):
    print(list1[x],end='\n')

# 遍历列表打印值
for x in list1:
    print(x,end='\n')

# 遍历列表,打印索引和值
for key,value in enumerate(list2):
    print(key,value)

# 列表推导式
list5 = [x**2 for x in list1]

# 同样支持切片操作
list6 = list1[::-1]
list7 = list1[0:2]
list8 = list1[:]


# 在列表的末尾添加一个元素
lst = [1, 2, 3]  
lst.append(4)  
print(lst)  # 输出: [1, 2, 3, 4]

# 将另一个可迭代对象(如列表、元组等)中的所有元素添加到列表的末尾
lst1 = [1, 2, 3]  
lst2 = [4, 5, 6]  
lst1.extend(lst2)  
print(lst1)  # 输出: [1, 2, 3, 4, 5, 6]

# 在指定索引处插入一个元素,索引超过列表长度时,会在末尾加上
lst = [1, 2, 4]  
lst.insert(2, 3)  
print(lst)  # 输出: [1, 2, 3, 4]

# 移除列表中第一个匹配的元素。如果元素不存在,则抛出 ValueError 异常
lst = [1, 2, 3, 2]  
lst.remove(2)  
print(lst)  # 输出: [1, 3, 2] 

# 移除并返回列表中指定索引处的元素。如果未指定索引,则默认移除并返回最后一个元素
lst = [1, 2, 3]  
print(lst.pop())  # 输出: 3  
print(lst)  # 输出: [1, 2]  
print(lst.pop(0))  # 输出: 1

# 返回列表中第一个匹配元素的索引。可以指定搜索的起始和结束位置。如果元素不存在,则抛出 ValueError 异常
lst = [1, 2, 3, 2]  
print(lst.index(2))  # 输出: 1

# 返回列表中指定元素的出现次数
lst = [1, 2, 2, 3, 2]  
print(lst.count(2))  # 输出: 3

# 对列表进行原地排序。可以指定排序关键字和排序顺序(升序或降序)
lst = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]  
lst.sort()  
print(lst)  # 输出: [1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]  
lst.sort(reverse=True)  
print(lst)  # 输出: [9, 6, 5, 5, 5, 4, 3, 3, 2, 1, 1]

# 返回一个新的已排序的列表,不改变原始列表
lst = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]  
new_lst = sorted(lst)  
print(new_lst)  # 输出: [1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]  
print(lst)  # 输出: [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5](原始列表未改变)

# 反转列表中的元素顺序
lst = [1, 2, 3, 4, 5]  
lst.reverse()  
print(lst)  # 输出: [5, 4, 3, 2, 1]

# 清除列表中的所有元素,使其成为空列表
lst = [1, 2, 3, 4, 5]  
lst.clear()  
print(lst)  # 输出: []

# 返回列表的一个浅拷贝
lst = [1, 2, [3, 4], 5]  
lst_copy = lst.copy()  
print(lst_copy)  # 输出: [1, 2, [3, 4], 5]  
lst_copy[2][0] = 99  
print(lst)  # 输出: [1, 2, [99, 4], 5](注意原始列表中的嵌套列表也被修改)


# 元组(tuple)

元组由多个用逗号隔开的值组成。构造 0 个或 1 个元素的元组比较特殊:为了适应这种情况,对句法有一些额外的改变。用一对空圆括号就可以创建空元组;只有一个元素的元组可以通过在这个元素后添加逗号来构建(圆括号里只有一个值的话不够明确)。丑陋,但是有效。

# 定义元组的方式


t = (12345, 54321, 'hello!')

empty = ()

singleton = 'hello',

singleton = ('hello',)

# 元组打包的例子
t = 12345, 54321, 'hello!'

# 元组序列解包,序列解包时,左侧变量与右侧序列元素的数量应相等
x,y,z = t

列表(list)和元组(tuple)都是序列类型,但它们之间有一个关键的区别:可变性。列表是可变的,元组是不可变的。

列表和元组之间的这种区别在设计和使用时是有其用途的: 列表:由于可以修改其内容,因此它非常适合用于需要在程序运行过程中动态更改的数据结构。 元组:由于其内容是不可变的,因此它更加轻量级和不可变。元组常常用于表示那些一旦设置后就不需要更改的固定值的集合,比如表示二维空间中的一个点 (x, y) 或表示函数的默认参数。

# 集合(set)

集合是由不重复元素组成的无序容器。基本用法包括成员检测、消除重复元素。集合对象支持合集、交集、差集、对称差分等数学运算。

创建集合用花括号或 set() 函数。注意,创建空集合只能用 set(),不能用 {}{} 创建的是空字典。

# 字典(dict)

可以把字典理解为 键值对 的集合,但字典的键必须是唯一的。花括号 {} 用于创建空字典。另一种初始化字典的方式是,在花括号里输入逗号分隔的键值对,这也是字典的输出方式。

检查字典里是否存在某个键,使用关键字 in。

字典的主要用途是通过关键字存储、提取值。用 del 可以删除键值对。用已存在的关键字存储值,与该关键字关联的旧值会被取代。通过不存在的键提取值,则会报错。