08 Python基础数据结构

目录:

1) 列表

2) 元组

3) 字符串

4) bytes

5) bytearray

6) 字典

7) 集合

8) 冻集合

 

 

"""
1. 列表特性
2. 创建
3. 增加
4. 删
5. 改
6. 查
7. 切片
8. 其他方法
9. for循环注意的点
10. 深浅copy问题
"""

列表特性:
1. 可变数据类型,可以存任意数据类型
2. 有序

Note:
1. 两个列表就算元素相同,但如果顺序不同,那么就是不同的列
ls = [1, 2, 3]
ls2 = [2, 1, 3]
print(ls == ls2)
2. 少用pop和insert,在数据量大的时候效率低

创建:
# 方法一
created_list1 = [] # 空列表
created_list1 = [1, '2', 3.0, 4+0j, b'abc', (1, 2), [1, 2], {1, 2}, {'k1': 'v1'}]
print(created_list1)

# 方法二
created_list2 = list() # 空列表
created_list2 = list(range(10))
print(created_list2)

# Note: 方法三
# 这种方式只是给created_list1起了一个别名,
# 他们操作的都是同一个对象
created_list3 = created_list1

增加:
ls = list(range(10))

# 追加
# 向列表最后追加一个任意类型的元素
ls.append('abc')
print(ls)

# 插入
# 在指定位置插入一个任意类型的元素
ls.insert(1, ['a', 'b', 'c'])
print(ls)

# 批量增加
# 在列表最后增加多个元素
ls.extend(['1d', '2e', '3f', '4g'])
print(ls)

# 批量插入
# 在指定位置插入多个元素
ls[0:0] = 'xyz' # ls[0:0]结果为空列表,在索引为0的前面插入'x', 'y', 'z'
print(ls)


删除:
# del
# del ls[1]
# del ls[0:0]
# print(ls)
# del可以删任何东西
# del ls
# print(ls)

# pop()
# 默认删除最后一个,并返回被删除的元素
# print(ls.pop())
# 可以指定删除谁
# print(ls.pop(-1))
# 如果索引超过范围,则报错IndexError

# remove()
# 删除遇到指定的第一个值,如果指定的值有多个,只删除遇到的第一个值
# ls.remove(1)
# print(ls)
# 如果将要删除的值不存在,则报错ValueError

# clear()
# 将列表清空
# ls.clear()
# print(ls)

# 将某一部分清空
# ls[:4] = []
# print(ls)
# ls[:] = [] # 与clear()作用一样
# print(ls)

改:
# 索引方式修改
ls[0] = 'a'
print(ls)

# 切片方式修改
# 等量修改
ls[0:4] = ['A', '一', '二', '三']
print(ls)
ls[:-7:-1] = ['九', '八', '七', '六', '五', '四']
print(ls)

# 不等量修改
ls[0:4] = list(range(20))
print(ls)
# 右往左不等量修改不允许,(毕竟列表在内存中的起始位置确定了,个人猜想)
# 超过范围,不允许
# ls[:-len(ls) + 1:-1] = list(range(100))
# print(ls)
# 未超过范围,不允许
# ls[:-7:-1] = [-1, -2, -3, -4, -5, -6, -7]
# print(ls)

# 当然,不等量修改是建立在步长为1的情况下
# 如果步长不为1,那么就只能等量修改
# ls[:4:2] = 'abcd' # 不允许
# print(ls)
ls[:4:2] = 'ab' # 正解
print(ls)

查:
Note:
负步长取的值是从右往左取,并且按照左往右方向排列 (总是弄混)

ls = [1, 2, 3]
print(ls)
print(ls[0])
print(ls[-1])

切片:
print(ls[0:5]) # 顾头不顾尾
print(ls[:5]) # 如果起始位置为0的话,可以省略
print(ls[1:-1]) # 有正索引,也有负索引;正,从左往右以0开始;负,从右往左以-1开始
print(ls[1:]) # 如果省略终止位置,则默认取到最后一个元素
print(ls[:]) # 取全部元素
print(ls[:6:2]) # 在[0 - 5]之间每隔两个取一个,2称之为步长;步长默认为1
print(ls[-9:-2:2])
# 如果步长为正整数,那么起始索引必须 < 终止索引
# 起始索引 <= 终止索引也可以,只不过取到的是空列表
print(ls[6:2:-1]) # 步长为负1,在[6 - 1]之间每隔一个取一个
print(ls[::-1]) # 列表反序输出
# 如果步长为负整数,那么起始索引必须 > 终止索引
# 起始索引 >= 终止索引也可以,只不过取到的是空列表
print(ls[:100]) # 切片的终止位置可以超出列表长度,尽可能地多取元素
print(ls[:100:2])
print(ls[:-100:-1])

其他方法:
*乘法操作
+加法操作
反转
排序
长度
计数
查询索引

ls = list(range(5))
print(ls)

# *乘法操作
ls = ls * 2
print(ls)

# +加法操作,类似extend()
ls = ls + ['a', 'b', 'c']
print(ls)
# 不仅可以加同类
# 还可以加不同类(容器类型),但必须是复合操作符
# 元组、列表、字符串、字典(加键)、集合、冻结集合
ls += 'efghi'
print(ls)
ls += 1, 2, 3
print(ls)

# 反转
ls.reverse()
print(ls)

# 排序
# 前提是元素类型要一致
ls2 = list(range(10))
ls2.sort() # 默认升序
print(ls2)
ls2.sort(reverse=True) # 降序
# key参数以后介绍
print(ls2)

# 长度
print(len(ls))
print(ls.__len__())
# len()内部就是调用的__len__()

# 计数
print(ls.count(2)) # 存在,则返回个数
print(ls.count(100)) # 不存在,则返回0

# 查询索引
# 在指定的范围内,返回遇到的第一个值的索引,如果有多个值相同,只返回第一个值的索引
print(ls.index(2))
print(ls.index(2, 1, 5))
# 如果查询的值不存在,则报错ValueError
# print(ls.index(100))

for循环注意的点
Note:
循环一个列表的时候,不要修改他的大小,会有问题
解决方法之一:
反向循环,从右往左循环
解决方法之二:
将要删除的元素放到另一个列表中


# 方法一:
for index in range(len(ls)-1, -1, -1):
if ls[index] % 2 == 0:
ls.pop(index)
# print(l1)

# 方法二:
del_ls = []
ls = list(range(10))
for item in ls:
if item % 2 == 0:
del_ls.append(item)
for item in del_ls:
ls.remove(item)

# 方法三:(但是我觉得这种浪费空间)
ls = list(range(10))
# for item in ls[::]:
for item in ls[::-1]:
if not item % 2:
ls.remove(item)
print(ls)

10. 深浅copy问题

ls = list(range(10))
ls.append(['a', 'b', 'c'])
# 浅copy
# copy的时候,只是创建了新的列表对象,新列表中每个元素的引用都是指向的被copy列表的每个元素的引用
ls2 = ls.copy()
print(ls2 is ls)
print(ls2[0] is ls[0]) # True,表示是同一块内存地址
print(ls2[-1] is ls[-1])
# 所以,对其中一个列表中的可变数据类型进行更改,另一个列表页能感知到
ls[-1].append('d')
print(ls2)

# 以下操作都是浅copy
# 创建了新的列表,只是copy了被copy列表对象的引用
# 虽然是不同的容器,但是里面的值都是同一个值
# 1. ls2 = ls.copy()
# 2. ls2 = ls[:]
# 3. ls2 = list(ls)
# 4. import copy
# ls2 = copy.copy(ls)

# 深copy
# Note: 非特殊情况,不要用深copy,当数据量大的时候,耗费容量
# 完全独立的两个列表对象,不管是容器本身还是里面的元素
# 准确来讲,是容器和里面的容器类型都是独立的
# 不可变数据类型在他们的一定范围内,都是同一个值,共用同一块内存

# import copy
# ls2 = copy.deepcopy(ls)
# print(ls2[-1] is ls[-1]) # 为False,说明不是同一块内存空间
# print(ls2[0] is ls[0]) # 不可变数据类型,在一定范围内,都是共用同一块内存空间

"""
1. 元组特性
2. 创建
3. 查
4. 切片
5. 其他方法
"""

元组特性:
相当于只读列表

1,不可变数据类型
2,元组本身不可变,但是如果其中包含其他可变数据类型,则可对这些类型进行修改
3,有序

应用场景:
1,显示地告诉别人,此处数据不可修改
2,数据库连接配置信息等

Note:
元组中最好不放其他容器类型
元组的效率实际上比列表高


创建:
# 方式一
tp = ()
tp = (1, 2, 3)
tp = (1,) # 逗号不能少
print(tp)

# 方式二
tp2 = 1, 2, 3
print(tp2)

# 方式三
tp3 = tuple(range(10))
print(tp3)

# 特别注意:
tp4 = tp3
# 道理跟列表一样

查:
tp[0]
tp[-1]

切片:
tp[:]

其他方法及操作:
count()
index()
tp *= 3
tp += tp2

"""
1. 字符串特性
2. 创建
3. 删
4. 查
5. 切片
6. 方法
基本方法
split和splitlines区别
strip注意事项:
isdigit / isdecimal / isnumeric区别
7. 字符串拼接
"""

字符串特性:
不可变数据类型

创建空字符串:
s = str()
s = ''
NOTE:
空字符串是任何字符串的子字符串

方法:
字母类:
captialize()
1,将字符串的第一个字母大写,如果第一个字符为字母的话
2,将字符串的除了第一个字母外其他字母部分变成小写,如果有的话
casefold()
有些国家的小写不一样
lower()
将字符串的字母部分变成小写
upper()
将字符串的字母部分变成大写
title()
将由非字母分隔的全部英文单词的第一个字母变成大写
swapcase()
大写变小写,小写变大写

对齐类:
center()
将字符串在指定宽度范围内居中对齐,两边默认填充字符为空格
ljust()
左对齐
rjust()
右对齐
zfill()
将字符串在指定宽度范围内右对齐,填充字符为0;
Note:
如果第一个字符是+或-,填充字符0将在其后填充

分隔类:
split()
默认分隔符为空白字符,maxsplit指定分隔的次数
rsplit()
从右边开始分隔
splitlines()
跟split('\n')有一点点区别,看后续介绍
参数 keepends=True/False,表示是否保留\n
partition()
一个元组(指定字符前的 ,指定字符, 指定字符后面的)
rpartition()
从右边开始分

剥夺类:
strip()
剥夺字符串两边指定的字符,默认为空白字符
lstrip()
剥夺字符串左边指定的字符,默认为空白字符
rstrip()
剥夺字符串右边指定的字符,默认为空白字符

编码解码类:
encode()
编码,默认utf-8,执行目标为str
encoding='utf-8'
errors='strict' 遇到非法字符时,直接抛出异常
ignore 忽略非法字符
replace 用?代替非法字符
decode()
解码,默认utf-8,执行目标为bytes

原则:用什么编码就用什么解码

加密类:
str.maketrans()
指定加密规则
str为str类或者任何str类型的数据
# 如果只有一个参数,那么参数必须为字典
# 字典的键可以为Unicode字符、Unicode字符对应的整数值、以及None,字典的值也一样;
# None表示删除
如果有两个参数或者三个
intab = '123' # intab和outtab要一一对应
outtab = 'abc'
deltab = 'qdy' # 也可以不指定deltab
rules = str.maketrans(intab, outtab, deltab)
print('123abcqdy123'.translate(rules))
translate()
加密

替换类:
replace()
将原字符串中的被替换字符串按照指定替换次数替换成新字符串,默认全部替换
expandtabs()
更改字符串中的\t的大小,默认为8
参数:tabsize

查找类:
index()
从左开始查找第一个指定字符对应的索引;
没有找到的话,则报异常
rindex()
从右开始查找第一个指定字符对应的索引;
没有找到的话,则报异常
find()
从左开始查找第一个指定字符对应的索引;
没有找到的话,则返回-1
rfind()
从右开始查找第一个指定字符对应的索引;
没有找到的话,则返回-1
count()
统计指定字符在字符串中出现的次数
没有指定字符的话,返回0

加入类:
join()
将一个字符加入到每一个元素为字符的迭代对象中

格式化类:
%
format()
format_map()

判断类:
startswith()
endswith()
isascii()
isalpha()
isupper()
islower()
istitle()
isalnum()
isdigit()
isdecimal()
isnumeric()
isspace()
isidentifier()
isprintable()

其他:
len()
del
+
*

# strip注意事项:
剥夺字符串两边指定的字符,默认为空白字符
空白字符包括:
\r
\n
\t
\v
\f
空格
Note:只要两边出现了指定字符串中的任意一个,
都将其去除,而不是说出现整体才去除(lstrip和rstrip同)


# split和splitlines区别
# 一,split
# 1, 当使用默认参数的时候以\t\f\v\r\n空格当分隔符
# 'abc\n' --> ['abc']
# 'abc\f\n' --> ['abc']
# '\n' --> []
# 2, 当指定了默认参数
# 'abc\n' --> ['abc', '']
# 'abc\f\n' --> ['abc', '', '']
# '\n' --> ['', '']
# 3, 当指定了除开默认参数的其他值
# 'abc123' --> ['abc', '']
# '123' --> ['', '']

# 二,splitlines
# 'abc\n' --> ['abc']
# 'abc\f\n' --> ['abc', ''] # 只有\f才会这样,估计把\f当作\n了
# 'abc\n\n' --> ['abc', '']
# '\n' --> ['']
# 相当于是:遇到\n,就把\n之前的字符以及\n拿出来,放到一个列表中。
然后再看keepends的值,如果为False,就不保留\n,如果为True,就保留\n

# isdigit / isdecimal / isnumeric区别

# isdigit()
# True: Unicode数字,全角数字(双字节), byte数字(单字节)
# False: 汉字数字, 罗马数字
# Error: 无
#
# isdecimal()
# True: Unicode数字,全角数字(双字节)
# False: 罗马数字,汉字数字
# Error: byte数字(单字节)
#
# isnumeric()
# True: Unicode数字,全角数字(双字节),罗马数字,汉字数字(壹、一)
# False: 无
# Error: byte数字(单字节)

# 字符串拼接

# 方式一:+加法操作符
s = '123'
s += '456'
print(s)

# 方式二:join
print('-'.join('123'))
# 加法与join的区别
# 1,如果拼接后的长度不超过20,+比join高效
# 2,如果长度超过20,则高版本解释器选择f'{}',低版本选用join

# 方式三:格式化类


"""
1. bytes特性
2. 创建
3. 删
4. 查
5. 切片
6. 方法
"""

bytes特性:
不可变数据类型

创建:
b = bytes()
b = b'' / B''
b = b'123abc' # 仅支持ascii字符

b = bytes(10)
b = bytes('琴师晃', encoding='utf-8', errors='strict')
b = bytes(range(10))

方法:
# 除了decimal和numeric其他都支持
# 自带2个方法
# hex()
# 将字符ASCII值二进制转换为字符串类型的十六进制
print(b'abc'.hex(), type(b'abc'.hex()))

# fromhex()
# 参数为字符串,内容为16进制的数码
# 成双出现,每一对是16进制
# 最后显示的结果为如果能用ASCII显示的就用ASCII字符显示,不能的话就16进制序列
print(bytes.fromhex('ff22'))

"""
1. bytearray特性
2. 创建
3. 删
4. 查
5. 切片
6. 方法
"""

bytearray特性:
可变的bytes

创建:
b = bytearray()
b = bytearray(b'123')
...

方法:
1. 支持str所有方法,除了decimal和numeric
2. 支持bytes的hex和fromhex
3. 支持列表的
append、insert、extend、
pop、remove、clear、copy、reverse

"""
1. 字典特性
2. 创建
3. 删
4. 改
4. 查
5. 循环
6. 方法
"""

字典特性:
1. 可变数据类型
2. 无序


创建:
NOTE:
键只能是可hash的,也就是不可变数据类型

# 方式一
dc = {}
dc = {'k1': 'v1', 'k2': 'v2'}
print(dc)
# Note:同时存在键1和True
# 只会显示1,True当1用
dc2 = {1: '1', True: 'True'}
print(dc2)

# 方式二
dc2 = dict()
dc2 = dict(dc)
dc2 = dict(name='123', age=20)
dc2 = dict([('sex', 'Male'), ('class', 2)])
print(dc2)

# 方式三
dc3 = dict.fromkeys(['name', 'age', 'sex'])
print(dc3)
dc3 = dict.fromkeys(['name', 'age', 'sex'], 10)
print(dc3)
# Note: 有一个坑,如果都初始化一个可变数据类型的话,
# 一个改,其他都改

增:
# 方式一
dc = {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
dc['k1'] = 90
print(dc)

# 方式二
# setdefault

# 方式三
# 键是唯一的,后来居上
# update()方法
dc2 = {'k1': 'qdy', 2: 3, (4, 6): [1, 2, 3]}
dc.update(dc2)
dc.update(k1='QinDongyu', name='第一')
dc.update([('sex', 'Male'), ('class', 2)])
print(dc)

删:
dc = {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
# 方式一
# del dc['k1']
# print(dc)

# 方式二
# pop()
# 如果键存在,则删除对应的键值对,并且返回键对应的值
# print(dc.pop('k1'))
# print(dc)
# 如果键不存在,并且不指定返回值的话,会报错KeyError
# print(dc.pop('k6'))
# print(dc.pop('k6', 'No this key'))
# print(dc)

# 方式三
# popitem()
# 随机删
# print(dc.popitem())

# 方式四
# clear()
# dc.clear()
# print(dc)

查:
# 方式一
dc = {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
print(dc['k1'])

# 方式二
# get()方法
# 如果键存在,则返回对应的值;
print(dc.get('k1'))
# 如果键不存在,默认情况下则返回None,可以自己指定返回的值
print(dc.get('k11'))
print(dc.get('k11', 'No this key'))

# 方式三
# setdefault()方法
# 如果键存在,则返回对应的值
print(dc.setdefault('k1'))
# 如果键不存在,则创建键'k1'以及值None,默认情况下,并返回创建的值
# print(dc.setdefault('k11'))
print(dc.setdefault('k11', 'v11'))
print(dc)

其他:
len()
copy()

循环:
Note:循环一个字典的时候,不要去修改他的大小,会出错

dc = {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
for key in dc:
print(key) # 打印的是键

# dc.keys()获取所有的键
# 可迭代、可转换、可参与集合运算、不支持索引
for key in dc.keys():
print(key)
else:
print(dc.keys())

# dc.values()获取所有的值
# 可迭代、可转换、不支持索引
for key in dc.values():
print(key)
else:
print(dc.values())

# dc.items()获取所有的键值对
# 可迭代、可转换、不支持索引
for key, value in dc.items():
print(key, value)
else:
print(dc.items())

# 其实这种方式比上面效率更高,因为下面直接通过hash取值
for key in dc:
print(key, dc[key])
else:
print(dc.items())


"""
1. 集合特性
2. 创建
3. 删
4. 增
5. 循环
6. 运算
"""

集合特性:
可变数据类型
去重
无序(虽然无序,但会按照某种规则显示)
(就是字典的键)

创建:
s = set()
s = set('123123123')

增:
st = {1, 2, 3}

# add
# 增加一个可hash的数据类型
st.add(4)
print(st)

# update
# 增加多个可hash的数据类型
st.update('abc')
print(st)
st.update(['A', 'Z'], '456', ('a', 'b'))
print(st)

st = set(range(10))

删:
# pop
# 随机删,并返回,如果集合为空,报错KeyError
ret = st.pop()
print(ret)
print(st)

# remove
# 删除一个元素,如果不存在,则报错KeyError
# st.remove(3)
# print(st)
# st.remove(10) # 报错

# discard
# 删除一个元素,如果不存在,不报错
st.discard(10)

# clear
# 清空
st.clear()

# copy()

运算:
st = {1, 2, 3, 4}
st2 = {2, 4, 'a', 'b'}

# 交
# 方式一:
# print(st & st2)
# st &= st2
# 方式二:
# print(st.intersection(st2))
# st.intersection_update(st2)
# print(st)

# 并
# 方式一:
# print(st | st2)
# st = st | st2
# print(st)
# 方式二:
# print(st.union(st2))

# 差
# 方式一:
# print(st - st2)
# print(st2 - st)
# st -= st2
# print(st)
# st2 -= st
# print(st2)
# 方式二:
# print(st.difference(st2))
# print(st2.difference(st))
# st.difference_update(st2)
# print(st)
# st2.difference_update(st)
# print(st2)

# 对称差集
# 方式一:
# print(st ^ st2)
# st ^= st2
# print(st)
# 方式二:
# print(st.symmetric_difference(st2))
# st.symmetric_difference_update(st2)
# print(st)

# 判断是否为子集
st = {2, 4}
st2 = {2, 4, 'a', 'b'}
# 方式一:
# <
# 要求父集必须大于子集
# print(st < st2) # 判断st是否是st2的子集
# st2 = {2, 4}
# print(st < st2)
# # <=
# print(st <= st2)
# 方式二:
# print(st.issubset(st2)) # issubset 等同于 <=

# 判断是否为父集
st = {2, 4}
st2 = {2, 4, 'a', 'b'}
# 方式一:
# >
# 要求父集必须大于子集
# print(st2 > st) # 判断st2是否是st的父集
# st2 = {2, 4}
# print(st < st2) # False
# # >=
# print(st2 >= st)
# 方式二:
# print(st2.issuperset(st)) # issuperset 等同于 >=

# 判断是否不相交
# print(st.isdisjoint(st2))

"""
1. 冻集合特性
2. 创建
3. 方法
"""

特性:
集合的不可变版本

创建:
fz = frozenset()
fz = frozenset('123123')

方法:

intersection
union
difference
symmetirc_difference
issubset
issuperset
isdisjointt

fz = frozenset(range(10))
fz2 = frozenset(range(10))
print(fz & fz2)
fz = fz & fz2 # 支持复合
print(fz)

posted @ 2019-03-26 19:12  hardySap  阅读(172)  评论(0编辑  收藏  举报