Python与医药数据处理 第六章

第六章 组合数据类型

img

组合数据类型 是否可变 是否有序 数据维度 存储内容
字符串 否 是 1 字符
元组 否 是 1 均有
列表 是 是 1 均有
集合 是 否 1 不可变数据类型
字典 是 否 2 键值对,键是不可变数据类型

注:这里的维度只一层该数据类型的维度,不考虑内部数据类型的嵌套,如列表里面存在列表

6.0 前置知识:可变数据类型

# Code 1
a = 1; b = 2
a = b
a = a + 1
print(b) 
# Code 2
a = [12, 34, 56]
b = [1, 2, 3, 4]
a = b
a.append([5, 6])
a = a + 1
print(b) 

上述两个例子中,Code 1 的运行结果毫无疑问是 \(2\),因为 b 从始至终没有改变过。那么如果我告诉你 Code 2 的运行结果是 \([1, 2, 3, 4, [5, 6]]\) 呢?如果你上课没有认真听,你大概率不会相信,但这是真的

Code 2 里的 b 明明也没有改变过,为什么输出的是 a 改变过的结果呢?因为 a 变的时候 b 也一起变了,这两个变量永远是绑定的

这与数据的存储方式有关,从是否可变的角度,数据分为可变数据类型与不可变数据类型,可变数据类型包括列表、字典、集合,不可变数据类型包括整数、浮点数、布尔值、字符串、元组、冻结集合(不要求了解)。

不可变数据类型在计算机中拥有其固定的地址,不可变数据的地址决定了变量的地址:

>>> a = 1
>>> id(a)
140736593725104
>>> b = 2
>>> id(b)
140736593725136
>>> a = b
>>> id(a)
140736593725136
>>> a = a - 1
>>> id(a) # a 的值回到 1,地址也回到了初值
140736593725104

可变数据类型在创建列表的过程中,地址是随意创建的;在赋值的过程中,被赋值变量地址会永久变更为赋值变量的地址(除非后续任意一方被重新定义或赋值),由于二者地址相同,所以内容也是绑定的,对任意一方进行操作,即是对该地址上的数据进行操作,因此另一个变量也应发生相同的改变,两个变量的内容永远是一样的

>>> a = [12, 34, 56]
>>> id(a)
1257369324096
>>> a = [12, 34, 56]
>>> id(a)
1257369256576
>>> a = [12, 34, 56]
>>> id(a) # 三次对变量 a 进行同一列表内容的赋值,地址都不相同
1257369323200
>>> a = [12, 34, 56]
>>> id(a)
1257369324864
>>> b = [1, 2, 3, 4]
>>> id(b)
1257368984192
>>> a = b
>>> a.append([5, 6])
>>> id(b)
1257368984192
>>> id(a) # 二者 id 相同
1257368984192
>>> print(a)
[1, 2, 3, 4, [5, 6]]
>>> print(b) # 修改后,二者内容相同
[1, 2, 3, 4, [5, 6]]
>>> a = [12, 34, 56] # 对变量 a 重新进行了定义,地址会刷新,但是 b 不会发生改变
>>> id(a)
1257369324096

6.1 序列类型

序列类型是有序的一维(线性)组合数据类型,包括字符串(str)、元组(tuple)、列表(list)三类

6.1.1 共有操作

因为字符串也是序列类型的一种,所以共有操作完全可以参考字符串来理解

  1. 操作符

img

  1. 内置函数

img

  1. 内置方法

img

  1. 遍历序列

(1)基于索引号遍历

for i in range(len(ls)): # 这应该是最直观的遍历方式了
    ...

(2)基于元素遍历

for each in ls: # 对元素按照顺序依次读取
    ...

插一道比较有意思的题目:

ls = ['a', 'b', 'c', 'd', 'd', 'd', 'd']
for i in ls:
    if i == 'd':
        ls.remove(i)
print(ls)  # 答案,输出结果应为:['a', 'b', 'c', 'd', 'd']

基于元素遍历的时候,循环的原理其实是在第 \(k\) 次循环中就选取当前状态下列表里第 \(k\) 的元素赋值给循环变量 \(i\),因此该题目的执行逻辑应如下:

# 进入循环体 ls == ['a', 'b', 'c', 'd', 'd', 'd', 'd']

# 第1次循环:取第1个元素,'a',不符合 if 表达式,结束该次循环
# 此时 ls == ['a', 'b', 'c', 'd', 'd', 'd', 'd']

# 第2次循环:取第2个元素,'b',不符合 if 表达式,结束该次循环
# 此时 ls == ['a', 'b', 'c', 'd', 'd', 'd', 'd']

# 第3次循环:取第3个元素,'c',不符合 if 表达式,结束该次循环
# 此时 ls == ['a', 'b', 'c', 'd', 'd', 'd', 'd']

# 第4次循环:取第4个元素,'d',符合 if 表达式,移除这个 'd',结束该次循环
# 此时 ls == ['a', 'b', 'c', 'd', 'd', 'd']

# 第5次循环:取第5个元素,'d',符合 if 表达式,移除这个 'd',结束该次循环(注意这里取的是此时状态下列表的第5个元素,即倒数第2个 'd')
# 此时 ls == ['a', 'b', 'c', 'd', 'd']

# 第6次循环:取第6个元素,发现此时列表已经没有第6个元素了,循环体终止结束,共进行5次循环

(3)枚举遍历序列

for index, herb in enumerate(ls):
    print(index, herb)

(4)多变量遍历序列

for d1, d2, d3, d4 in ["上下左右", "北南西东"]:
    print(d1, d2, d3, d4)

6.1.2 生成元组

  1. 函数多个返回值
x = divmod(5, 3)
  1. 多变量同步赋值
tp = eval(input("请输入3个整数,用逗号分隔:"))
  1. 循环遍历
numbers = tuple(i for i in range(10))

6.1.3 元组的个性化操作

元组属于不可变序列,访问和处理速度比列表更快。因此元组的元素是不支持修改的,如果执行修改语句会报错异常 'TypeError'

如果元组的元素是可变数据类型,那么元素的值是可以被改变的,但是不建议这么使用,因为这个时候使用元组本身就毫无意义

6.1.4 生成列表

(1)方括号生成法

ls = [1, 352, 'abc', [], 1]

(2)函数/方法返回生成法

ls1 = sorted('13254')
ls2 = s.split("、")

(3)list生成法

ls = list(zip([1, 2, 3], ('a', 'b', 'c')))

(4)map()映射法

ls = list(map(lambda x: x[0], ls))

(5)列表式生成法

ls1 = [x ** 2 for x in range(10)]

6.1.5 列表的个性化操作

  1. 操作符

img

  1. 内置函数

img

  1. 内置方法

img

基本上看表格都能理解,关于内置方法,简要谈一下几个需要注意的函数:

ls.insert(i, x):添加在原列表中索引号为 \(i-1\) 的元素后面,如

>>> ls = [0, 2, 4, 6, 8]
>>> ls.insert(1, 1) # 在索引号为 0 的元素后面插入
[0, 1, 2, 4, 6, 8]

ls.reverse() 和 ls.sort() 都有对应的独立函数 reversed 和 sorted,其中 sorted() 在第五章内置函数章节有所提及,reversed(ls) 返回的是反转后得到的迭代器,需要用 list() 函数将其转化为列表将其显化

ls2 = list(reversed(ls1))

6.2 集合(set)

集合是一类一维无序可变数据类型,集合的主要特点是不重复性和无序性

集合的元素只能是固定数据类型(不可变数据类型),包括:数字类型、字符串类型、逻辑类型、不包含可变数据类型元素的元组

6.2.1 生成集合

(1)表示法

a = {1, 2, 3}

(2)set() 函数法

a = set('apple')
a = set() # 该语句用以生成空集合
# a = {} 不能用于生成空集合,该命令生成的是空字典

6.2.2 集合的操作

  1. 操作符

img

  1. 内置函数

img

  1. 内置方法

img

6.3 字典(dict)

字典的结构:{<键1>:<值1>, <键2>:<值2>, ..., <键n>:<值n>}

字典是一类二维无序组合数据类型由键值对构成,元素为键值对

键只能取固定数据类型,值不限

字典是无序结构,键具有不重复性

6.3.1 生成字典

生成字典通常使用直接表示法

dic = {<键1>:<值1>, <键2>:<值2>, ..., <键n>:<值n>}
# 花括号内无内容时,生成空字典

6.3.2 字典的个性化操作

  1. 基本操作

<字典变量[<键>]>:检索键对应的值

<键> in <字典变量>:成员运算,判断键是否在字典里

<字典变量[<键>]> = 值:如果 <键> 为字典内已有的,则更新对应的值;如果 <键> 在字典内没有,就创建新的键值对

  1. 内置函数

del(<字典变量>[<键>]):删除元素,删除键对应的键值对

  1. 内置方法

img

对于返回类型为 dict_keys 和 dict_values 的函数,可以使用 list() 函数等对数据进行显化:

>>> dic = {'a':1,'b':2,'c':3}
>>> dic.keys()
dict_keys(['a', 'b', 'c'])
>>> list(dic.keys())
['a', 'b', 'c']
  1. 遍历字典

由于“键值对”中的键相当于所以,所以 for 循环的循环变量名是字典的键,如:

dic = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
for i in dic:
    print("键:", i)
    print("值:", dic.get(i))

6.4 jieba库

jieba.cut(s):精确模式,返回一个可迭代的数据类型

jieba.cut(s, cut_all = True):全模式,返回一个可迭代的数据类型

jieba.cut_for_search(s):搜索引擎模式,返回一个可迭代的数据类型

jieba.lcut(s):精确模式,返回一个列表

jieba.lcut(s, cut_all = True):全模式,返回一个列表

jieba.lcut_for_search(s):搜索引擎模式,返回一个列表

jieba.add_word(w):向用来检索词汇的词库里面添加新词

前六个方法为分词的方法,分词分为精确模式,全模式,搜索引擎模式:

精确模式:将文字按照语义最尽可能精确地切开,适用于文本分析

全模式:把句子中所有可以分成词的词语都扫描出来,速度非常快,但难以消除歧义

搜索引擎模式:在精确模式的基础上,对长词进行进一步切分,将切分出来的词语补充进去

六个分词方法中,后三个 'l' 开头的返回的都是列表类型,方便我们后续进行操作,故一般多使用这三个方法

6.5 词频统计

img

posted @ 2025-06-25 03:25  凛凛雾  阅读(46)  评论(0)    收藏  举报