当前位置: 首页 > news >正文

【python - 数据】

一、序列

序列(sequence)是一组有顺序的值的集合,是计算机科学中的一个强大且基本的抽象概念。序列并不是特定内置类型或抽象数据表示的实例,而是一个包含不同类型数据间共享行为的集合。也就是说,序列有很多种类,但它们都具有共同的行为。特别是:

  • 长度(Length):序列的长度是有限的,空序列的长度为 0。

  • 元素选择(Element selection):序列中的每个元素都对应一个小于序列长度的非负整数作为其索引,第一个元素的索引从 0 开始。

Python 包含几种内置的序列数据类型,其中最重要的是列表(list)。

1.1、列表

列表(list)是一个可以有任意长度的序列。列表有大量的内置行为,以及用于表达这些行为的特定语法。我们已经见过列表字面量(list literal),它的计算结果是一个 list 实例,以及一个计算结果为列表中元素值的元素选择表达式。list 内置的 len 函数返回序列的长度。如下,digits 是一个包含四个元素的列表,索引为 3 的元素是 8。

>>> digits = [1, 8, 2, 8]
>>> len(digits)
4
>>> digits[3]
8

此外,多个列表间可以相加,并且列表可以乘以整数。对于序列来说,加法和乘法并不是作用在内部元素上的,而是对序列自身进行组合和复制。也就是说,operator 模块中的 add 函数(和 + 运算符)会生成一个为传入列表串联的新列表。operator 中的 mul 函数(和 * 运算符)可接收原列表和整数 k 来返回一个内容为原列表内容 k 次重复的新列表。

>>> [2, 7] + digits * 2
[2, 7, 1, 8, 2, 8, 1, 8, 2, 8]

 

任何值都可以包含在一个列表中,包括另一个列表。在嵌套列表中可以应用多次元素选择,以选择深度嵌套的元素。

>>> pairs = [[10, 20], [30, 40]]
>>> pairs[1]
[30, 40]
>>> pairs[1][0]
30

1.2、序列遍历

在许多情况下,我们希望依次遍历序列的元素并根据元素值执行一些计算。这种情况十分常见,所以 Python 提供了一个额外的控制语句来处理序列的数据:for 循环语句。

考虑统计一个值在序列中出现了多少次的问题。我们可以使用 while 循环实现一个函数。

>>> def count(s, value):"""统计在序列 s 中出现了多少次值为 value 的元素"""total, index = 0, 0while index < len(s):if s[index] == value:total = total + 1index = index + 1return total
>>> count(digits, 8)
2

Python 的 for 循环可以通过直接遍历元素值来简化函数,相比 while 循环无需引入变量名 index

>>> def count(s, value):"""统计在序列 s 中出现了多少次值为 value 的元素"""total = 0for elem in s:if elem == value:total = total + 1return total
>>> count(digits, 8)
2

一个 for 循环语句由如下格式的单个子句组成:

for <name> in <expression>:<suite>

for 循环语句按以下过程执行:

  1. 执行头部(header)中的 <expression>,它必须产生一个可迭代(iterable)的值
  2. 对该可迭代值中的每个元素,按顺序:
    1. 将当前帧的 <name> 绑定到该元素值
    2. 执行 <suite>

此执行过程中使用了可迭代值。列表是序列的一种,而序列是可迭代值,它们中的元素按其顺序进行迭代。Python 还包括其它可迭代类型,但我们现在将重点介绍序列。

这个计算过程中的一个重要结果是:执行 for 语句后,<name> 将绑定到序列的最后一个元素。所以 for 循环引入了另一种可以通过语句更新环境的方法。

序列解包(Sequence unpacking):程序中的一个常见情况是序列的元素也是序列,但所有内部序列的长度是固定相同的。for 循环可以在头部的 <name> 中包含多个名称,来将每个元素序列“解包”到各自的元素中

例如,我们可能有一个包含以列表为元素的 pairs,其中所有内部列表都只包含 2 个元素。

>>> pairs = [[1, 2], [2, 2], [2, 3], [4, 4]]

此时我们希望找到有多少第一元素和第二元素相同的内部元素对,下面的 for 循环在头部中包括两个名称,将 x 和 y 分别绑定到每对中的第一个元素和第二个元素。

>>> same_count = 0
>>> for x, y in pairs:if x == y:same_count = same_count + 1
>>> same_count
2

这种将多个名称绑定到固定长度序列中的多个值的模式称为序列解包(sequence unpacking),这与赋值语句中将多个名称绑定到多个值的模式类似。

范围(Ranges)range 是 Python 中的另一种内置序列类型,用于表示整数范围。范围是用 range 创建的,它有两个整数参数:起始值和结束值加一。(其实可以有三个参数,第三个参数为步长,感兴趣可以自行搜索)

>>> range(1, 10)  # 包括 1,但不包括 10
range(1, 10)

将 range 的返回结果传入 list 构造函数,可以构造出一个包含该 range 对象中所有值的列表,从而简单的查看范围中包含的内容。

>>> list(range(5, 8))
[5, 6, 7]

如果只给出一个参数,参数将作为双参数中的“结束值加一”,获得从 0 到结束值的范围。(其实单参数就相当于默认了起始值从 0 开始)

>>> list(range(4))
[0, 1, 2, 3]

范围通常出现在 for 循环头部中的表达式,以指定 <suite> 应执行的次数。一个惯用的使用方式是:如果 <name> 没有在 <suite> 中被使用到,则用下划线字符 "_" 作为 <name>

>>> for _ in range(3):print('Go Bears!')Go Bears!
Go Bears!
Go Bears!

对解释器而言,这个下划线只是环境中的另一个名称,但对程序员具有约定俗成的含义,表示该名称不会出现在任何未来的表达式中

1.3、序列处理

序列是复合数据的一种常见形式,常见到整个程序都可能围绕着这个单一的抽象来组织。具有序列作为输入输出的模块化组件可以混用和匹配以实现数据处理。将序列处理流程中的所有操作链接在一起可以定义复杂组件,其中每个操作都是简单和集中的。

列表推导式(List Comprehensions):许多序列操作可以通过对序列中的每个元素使用一个固定表达式进行计算,并将结果值保存在结果序列中。在 Python 中,列表推导式是执行此类计算的表达式。

>>> odds = [1, 3, 5, 7, 9]
>>> [x+1 for x in odds]
[2, 4, 6, 8, 10]

上面的 for 关键字并不是 for 循环的一部分,而是列表推导式的一部分,因为它被包含在方括号里。子表达式 x+1 通过绑定到 odds 中每个元素的变量 x 进行求值,并将结果值收集到列表中。

另一个常见的序列操作是选取原序列中满足某些条件的值。列表推导式也可以表达这种模式,例如选择 odds 中所有可以整除 25 的元素。

>>> [x for x in odds if 25 % x == 0]
[1, 5]

 

列表推导式的一般形式是:

[<map expression> for <name> in <sequence expression> if <filter expression>]

为了计算列表推导式,Python 首先执行 <sequence expression>,它必须返回一个可迭代值。然后将每个元素值按顺序绑定到 <name>,再执行 <filter expression>,如果结果为真值,则计算 <map expression><map expression> 的结果将被收集到结果列表中。

聚合(Aggregation):序列处理中的第三种常见模式是将序列中的所有值聚合为一个值。内置函数 summin 和 max 都是聚合函数的示例。

通过组合对每个元素进行计算、选择元素子集和聚合元素的模式,我们就可以使用序列处理的方法解决问题。

完美数是等于其约数之和的正整数。n 的约数指的是小于 n 且可以整除 n 的正整数。可以使用列表推导式来列出 n 的所有约数。

>>> def divisors(n):return [1] + [x for x in range(2, n) if n % x == 0]>>> divisors(4)
[1, 2]
>>> divisors(12)
[1, 2, 3, 4, 6]

通过 divisors,我们可以使用另一个列表推导式来计算 1 到 1000 的所有完美数。(1 通常也被认为是一个完美数,尽管它不符合我们对约数的定义。)

>>> [n for n in range(1, 1000) if sum(divisors(n)) == n]
[1, 6, 28, 496]

我们可以重用定义的 divisors 来解决另一个问题:在给定面积的情况下计算具有整数边长的矩形的最小周长。矩形的面积等于它的高乘以它的宽,因此给定面积和高度,我们可以计算出宽度。

使用 assert 可以规定宽度和高度都能整除面积,以确保边长是整数。

>>> def width(area, height):assert area % height == 0return area // height

矩形的周长是其边长之和,由此我们可以定义 perimeter

>>> def perimeter(width, height):return 2 * width + 2 * height

对于边长为整数的矩形来说,高度必是面积的约数,所以我们可以考虑所有可能的高度来计算最小周长。

>>> def minimum_perimeter(area):heights = divisors(area)perimeters = [perimeter(width(area, h), h) for h in heights]return min(perimeters)>>> area = 80
>>> width(area, 5)
16
>>> perimeter(16, 5)
42
>>> perimeter(10, 8)
36
>>> minimum_perimeter(area)
36
>>> [minimum_perimeter(n) for n in range(1, 10)]
[4, 6, 8, 8, 12, 10, 16, 12, 12]

高阶函数(Higher-Order Functions):序列处理中常见的模式可以使用高阶函数来表示。首先可以将对序列中每个元素进行表达式求值表示为将某个函数应用于序列中每个元素。

>>> def apply_to_all(map_fn, s):return [map_fn(x) for x in s]

仅选择满足表达式条件的元素也可以通过对每个元素应用函数来表示。

>>> def keep_if(filter_fn, s):return [x for x in s if filter_fn(x)]

最后,许多形式的聚合都可以被表示为:将双参数函数重复应用到 reduced 值,并依次对每个元素应用。

>>> def reduce(reduce_fn, s, initial):reduced = initialfor x in s:reduced = reduce_fn(reduced, x)return reduced

例如,reduce 可用于将序列内的所有元素相乘。使用 mul 作为 reduce_fn,1 作为初始值,reduce 可用于将序列内的数字相乘。

>>> reduce(mul, [2, 4, 8], 1)
64

同样也可以用这些高阶函数来寻找完美数。

>>> def divisors_of(n):divides_n = lambda x: n % x == 0return [1] + keep_if(divides_n, range(2, n))>>> divisors_of(12)
[1, 2, 3, 4, 6]
>>> from operator import add
>>> def sum_of_divisors(n):return reduce(add, divisors_of(n), 0)>>> def perfect(n):return sum_of_divisors(n) == n>>> keep_if(perfect, range(1, 1000))
[1, 6, 28, 496]

约定俗成的名字(Conventional Names):在计算机科学中,apply_to_all 更常用的名称是 map,而 keep_if 更常用的名称是 filter。Python 中内置的 map 和 filter 是以上函数的不以列表为返回值的泛化形式,这些函数在第 4 章中介绍。上面的定义等效于将内置 map 和 filter 函数的结果传入 list 构造函数。

>>> apply_to_all = lambda map_fn, s: list(map(map_fn, s))
>>> keep_if = lambda filter_fn, s: list(filter(filter_fn, s))

reduce 函数内置于 Python 标准库的 functools 模块中。在此版本中,initial 参数是可选的。

>>> from functools import reduce
>>> from operator import mul
>>> def product(s):return reduce(mul, s)>>> product([1, 2, 3, 4, 5])
120

在 Python 程序中,更常见的是直接使用列表推导式而不是高阶函数,但这两种序列处理方法都被广泛使用。

1.4、序列抽象

成员资格(Membership):可用于测试某个值在序列中的成员资格。Python 有两个运算符 in 和 not in,它们的计算结果为 True 或 False,取决于元素是否出现在序列中。

>>> digits
[1, 8, 2, 8]
>>> 2 in digits
True
>>> 1828 not in digits
True

切片(Slicing):一个切片是原始序列的任意一段连续范围,由一对整数指定。和 range 构造函数一样,第一个整数表示起始索引,第二个整数是结束索引加一。(译者注:和前面的 range 一样,其实还有第三个参数代表步长,最经典的例子是使用 s[::-1] 得到 s 的逆序排列,具体可以自行搜索)

在 Python 中,序列切片的表达方式类似于元素选择,都使用方括号,方括号中的冒号用于分隔起始索引和结束索引。

如果起始索引或结束索引被省略则默认为极值:当起始索引被省略,则起始索引为 0;当结束索引被省略,则结束索引为序列长度,即取到序列最后一位。

>>> digits[0:2]
[1, 8]
>>> digits[1:]
[8, 2, 8]

1.5、字符串 

Python 中文本值的内置数据类型称为字符串(string),对应构造函数 str。在 Python 中,表示、表达和操作字符串的细节有很多。

字符串字面量(string literals)可以表示任意文本,使用时将内容用单引号或双引号括起来。

>>> 'I am string!'
'I am string!'
>>> "I've got an apostrophe"
"I've got an apostrophe"
>>> '您好'
'您好'

我们已经在代码中看到过字符串,比如文档字符串(docstring)、print 的调用中,以及 assert 语句中的错误消息。

字符串同样满足我们在本节开头介绍的序列的两个基本条件:它们具有长度且支持元素选择。字符串中的元素是只有一个字符的字符串。字符可以是字母表中的任何单个字母、标点符号或其他符号。

与其他编程语言不同,Python 没有单独的字符类型,任何文本都是字符串。表示单个字符的字符串的长度为 1。

>>> city = 'Berkeley'
>>> len(city)
8
>>> city[3]
'k'

与列表一样,字符串也可以通过加法和乘法进行组合。

>>> 'Berkeley' + ', CA'
'Berkeley, CA'
>>> 'Shabu ' * 2
'Shabu Shabu '

成员资格(Membership):字符串的行为与 Python 中的其他序列类型有所不同。字符串抽象不符合我们对列表和范围描述的完整序列抽象。具体来说,成员运算符 in 应用于字符串时的行为与应用于序列时完全不同,它匹配的是子字符串而不是元素。(如果字符串的行为和列表的一样,则应该匹配字符串的元素,即单个字符,但实际上匹配的是任意子字符串)

>>> 'here' in "Where's Waldo?"
True

多行字面量(Multiline Literals):字符串可以不限于一行。跨越多行的字符串字面量可以用三重引号括起,我们已经在文档字符串中广泛使用了这种三重引号。

>>> """The Zen of Python
claims, Readability counts.
Read more: import this."""
'The Zen of Python\nclaims, "Readability counts."\nRead more: import this.'

在上面的打印结果中,\n(读作“反斜杠 n”)是一个表示换行的单个元素。尽管它显示为两个字符(反斜杠和 "n" ),但为了便于计算长度和元素选择,它被视为单个字符。

字符串强制转换(String Coercion):通过以对象值作为参数调用 str 的构造函数,可以从 Python 中的任何对象创建字符串。字符串的这一特性在用构造各种类型对象的描述性字符串时非常有用。

>>> str(2) + ' is an element of ' + str(digits)
'2 is an element of [1, 8, 2, 8]'

二、数据抽象

2.1、示例:有理数

有理数是整数的比值,并且有理数是实数的一个重要子类。 1/3 或 17/29 等有理数通常写为:

<分子>/<分母>

其中 <分子> 和 <分母> 都是整数值的占位符,这两个部分能够准确表示有理数的值。实际上的整数除以会产生 float 近似值,失去整数的精确精度。

>>> 1/3
0.3333333333333333
>>> 1/3 == 0.333333333333333300000  # 整数除法得到近似值
True

但是,我们可以通过将分子和分母组合在一起来创建有理数的精确表示。

通过使用函数抽象,我们可以在实现程序的某些部分之前开始高效地编程。我们首先假设已经存在了一个从分子和分母构造有理数的方法,再假设有方法得到一个给定有理数的分子和分母。进一步假设得到以下三个函数:

  • rational(n, d) 返回分子为 n、分母为 d 的有理数
  • numer(x) 返回有理数 x 的分子
  • denom(x) 返回有理数 x 的分母

我们在这里使用了一个强大的程序设计策略:一厢情愿(wishful thinking)。即使我们还没有想好有理数是如何表示的,或者函数 numerdenom 和 rational 应该如何实现。但是如果我们确实定义了这三个函数,我们就可以进行加法、乘法、打印和测试有理数是否相等:

>>> def add_rationals(x, y):nx, dx = numer(x), denom(x)ny, dy = numer(y), denom(y)return rational(nx * dy + ny * dx, dx * dy)>>> def mul_rationals(x, y):return rational(numer(x) * numer(y), denom(x) * denom(y))>>> def print_rational(x):print(numer(x), '/', denom(x))>>> def rationals_are_equal(x, y):return numer(x) * denom(y) == numer(y) * denom(x)

现在我们有了选择器函数 numer 和 denom 以及构造函数 rational 定义的有理数运算,但还没有定义这些函数。我们需要某种方法将分子和分母粘合在一起形成一个复合值。

2.2、对

为了使我们能够实现具体的数据抽象,Python 提供了一个名为 list 列表的复合结构,可以通过将表达式放在以逗号分隔的方括号内来构造。这样的表达式称为列表字面量。

>>> [10, 20]
[10, 20]

可以通过两种方式访问 ​​ 列表元素。第一种方法是通过我们熟悉的多重赋值方法,它将列表解构为单个元素并将每个元素与不同的名称绑定。

>>> pair = [10, 20]
>>> pair
[10, 20]
>>> x, y = pair
>>> x
10
>>> y
20

访问列表中元素的第二种方法是通过元素选择运算符,也使用方括号表示。与列表字面量不同,直接跟在另一个表达式之后的方括号表达式不会计算为 list 值,而是从前面表达式的值中选择一个元素。

>>> pair[0]
10
>>> pair[1]
20

Python 中的列表(以及大多数其他编程语言中的序列)是从 0 开始索引的,这意味着索引 0 选择第一个元素,索引 1 选择第二个元素,以此类推。对于这种索引约定的一种直觉是,索引表示元素距列表开头的偏移量。

元素选择运算符的等效函数称为 getitem ,它也使用 0 索引位置从列表中选择元素。

>>> from operator import getitem
>>> getitem(pair, 0)
10
>>> getitem(pair, 1)
20

双元素列表并不是 Python 中表示对的唯一方法。将两个值捆绑在一起成为一个值的任何方式都可以被认为是一对。列表是一种常用的方法,它也可以包含两个以上的元素,我们将在本章后面进行探讨。

代表有理数:我们现在可以将有理数表示为两个整数的对:一个分子和一个分母。

>>> def rational(n, d):return [n, d]>>> def numer(x):return x[0]>>> def denom(x):return x[1]

连同之前定义的算术运算,我们可以使用我们定义的函数来操作有理数。

>>> half = rational(1, 2)
>>> print_rational(half)
1 / 2
>>> third = rational(1, 3)
>>> print_rational(mul_rationals(half, third))
1 / 6
>>> print_rational(add_rationals(third, third))
6 / 9

如上面的示例所示,我们的有理数实现不会将有理数简化为最小项。可以通过更改 rational 的实现来弥补这个缺陷。如果我们有一个计算两个整数的最大公分母的函数,我们可以用它在构造对之前将分子和分母减少到最低项。与许多有用的工具一样,这样的功能已经存在于 Python 库中。

>>> from fractions import gcd # python3.10变from math import gcd
>>> def rational(n, d):g = gcd(n, d)return (n//g, d//g)

// 表示整数除法,它会将除法结果的小数部分向下舍入。因为我们知道 g 会将 n 和 d 均分,所以在这种情况下整数除法是精确的。这个修改后的 rational 实现会确保有理数以最小项表示。

>>> print_rational(add_rationals(third, third))
2 / 3

这种改进是通过更改构造函数而不更改任何实现实际算术运算的函数来实现的。

2.3、抽象屏障

在继续更多复合数据和数据抽象的示例之前,让我们考虑一下有理数示例引发的一些问题。我们根据构造函数 rational 和选择器函数 numer 和 denom 来定义操作。一般来说,数据抽象的基本思想是确定一组基本操作,根据这些操作可以表达对某种值的所有操作,然后仅使用这些操作来操作数据。通过以这种方式限制操作的使用,在不改变程序行为的情况下改变抽象数据的表示会容易得多

对于有理数,程序的不同部分使用不同的操作来处理有理数,如此表中所述。

该程序的一部分...把有理数当作...仅使用...
使用有理数进行计算整个数据值add_rational, mul_rational, rationals_are_equal, print_rational
创建有理数或操作有理数分子和分母rational, numer, denom
为有理数实现选择器和构造器二元列表列表字面量和元素选择

在上面的每一层中,最后一列中的函数会强制实施抽象屏障(abstraction barrier)。这些功能会由更高层次调用,并使用较低层次的抽象实现。

当程序中有一部分本可以使用更高级别函数但却使用了低级函数时,就会违反抽象屏障。例如,计算有理数平方的函数最好用 mul_rational 实现,它不对有理数的实现做任何假设。

>>> def square_rational(x):return mul_rational(x, x)

直接引用分子和分母会违反一个抽象屏障。

>>> def square_rational_violating_once(x):return rational(numer(x) * numer(x), denom(x) * denom(x))

假设有理数会表示为双元素列表将违反两个抽象屏障

>>> def square_rational_violating_twice(x):return [x[0] * x[0], x[1] * x[1]]

抽象屏障使程序更易于维护和修改。依赖于特定表示的函数越少,想要更改该表示时所需的更改就越少。计算有理数平方的所有这些实现都具有正确的行为,但只有第一个函数对未来的更改是健壮的。即使我们修改了有理数的表示,square_rational 函数也不需要更新。相比之下,当选择器函数或构造函数签名发生变化后,square_rational_violating_once 就需要更改,而只要有理数的实现发生变化,square_rational_violating_twice 就需要更新。

2.4、数据的属性

抽象屏障塑造了我们思考数据的方式。有理数的表示不限于任何特定的实现(例如二元素列表);它就是由 rational 返回的值,然后可以传递给 numer 和 denom 。此外,构造器和选择器之间必须保持适当的关系。也就是说,如果我们从整数 n 和 d 构造一个有理数 x ,那么 numer(x)/denom(x) 应该等于 n/d 。

通常,我们可以使用选择器和构造器的集合以及一些行为条件来表达抽象数据。只要满足行为条件(比如上面的除法属性),选择器和构造器就构成了一种数据的有效表示。抽象屏障下的实现细节可能会改变,但只要行为没有改变,那么数据抽象就仍然有效,并且使用该数据抽象编写的任何程序都将保持正确。

这种观点可以广泛应用,包括我们用来实现有理数的对。我们从来没有真正谈论什么是一对,只是语言提供了创建和操作二元列表的方法。我们需要实现一对的行为是它将两个值粘合在一起。作为一种行为条件,

  • 如果一对 p 由值 x 和 y 构成,则 select(p, 0) 返回 x, select(p, 1) 返回 y

我们实际上并不一定需要 list 类型来创建对,作为替代,我们可以用两个函数 pair 和 select 来实现这个描述以及一个二元列表。

>>> def pair(x, y):"""Return a function that represents a pair."""def get(index):if index == 0:return xelif index == 1:return yreturn get>>> def select(p, i):"""Return the element at index i of pair p."""return p(i)

通过这个实现,我们可以创建和操作对。

>>> p = pair(20, 14)
>>> select(p, 0)
20
>>> select(p, 1)
14

这种高阶函数的使用完全不符合我们对数据应该是什么的直觉概念。但尽管如此,这些函数足以在我们的程序中表示对,也足以表示复合数据。

这种表示对的函数表示的重点并不是 Python 实际上以这种方式工作(出于效率原因,列表更直接地实现),而是它可以以这种方式工作。函数表示虽然晦涩难懂,但却是表示对的一个完全合适的方法,因为它满足了表示对需要满足的唯一条件。数据抽象的实践使我们能够轻松地在表示之间切换。

2.5、字典

字典(Dictionary)是 Python 的内置类型,用来存储和操作带有映射关系的数据。一个字典包含一组键值对(key-value pairs),其中键和值都是对象。字典的主要目的是抽象一组基于键值对的数据,在字典中,数据的存取都是基于带有描述性信息的键而不是连续递增的数字。

字典的 key 一般都是字符串(String),因为我们习惯用字符串来表示某个事物的名称。下面这个字典字面量表示了一组罗马数字:

>>> numerals = {'I': 1.0, 'V': 5, 'X': 10}

在字典元素中查找某个 key 对应的 value,与我们之前在列表中使用的操作符相同:

>>> numerals['X']
10

在字典中,一个 key 只能对应一个 value。无论是向字典中增加新的键值对,还是修改某个 key 值对应的 value,都可以使用赋值语句实现:

>>> numerals['I'] = 1
>>> numerals['L'] = 50
>>> numerals
{'I': 1, 'X': 10, 'L': 50, 'V': 5}

注意上面的打印输出,'L' 并没有被插入到字典的末尾。字典是无序的。当我们打印一个字典的时候,键值对会以某种顺序被渲染在页面上,但作为 Python 语言的使用者,我们无法预测这个顺序是什么样的。如果我们多运行几次这个程序,字典输出的顺序可能会有所变化。

Python 3.7 及以上版本的字典顺序会确保为插入顺序,此行为是自 3.6 版开始的 CPython 实现细节,字典会保留插入时的顺序,对键的更新也不会影响顺序,删除后再次添加的键将被插入到末尾

字典类型也提供了一系列遍历字典内容的方法。keysvalues 和 items 方法都返回一个可以被遍历的值。

>>> sum(numerals.values())
66

利用 dictionary 构造方法,我们可以将一个由键值对组成的列表转化为一个字典对象。

>>> dict([(3, 9), (4, 16), (5, 25)])
{3: 9, 4: 16, 5: 25}

但是字典类型也有一些限制:

  • 字典的 key 不可以是可变数据,也不能包含可变数据
  • 一个 key 只能对应一个 value

第一个限制是由于字典在 Python 内部的实现机制导致的。字典类型具体的实现机制不在这里展开。简单来说,假设是 key 值告诉 Python 应该去内存中的什么位置找对应的键值对,如果 key 值本身发生了变化,那键值对在内存中的位置信息也就丢失了。比如,元组可以被用来做字典的 key 值,但是列表就不可以。

第二个限制是因为字典本身被设计为根据 key 去查找 value,只有 key 和 value 的绑定关系是唯一确定的,我们才能够找到对应的数据。

字典中一个很有用的方法是 get,它返回指定 key 在字典中对应的 value;如果该 key 在字典中不存在,则返回默认值。get 方法接收两个参数,一个 key,一个默认值。

>>> numerals.get('A', 0)
0
>>> numerals.get('V', 0)
5

与列表类似,字典也有推导式语法。其中,key 和 value 使用冒号分隔。字典推导式会创建一个新的字典对象。

>>> {x: x*x for x in range(3,6)}
{3: 9, 4: 16, 5: 25}

键不可以是列表、字典或语言中任何可变类型。

相关文章:

【python - 数据】

一、序列 序列&#xff08;sequence&#xff09;是一组有顺序的值的集合&#xff0c;是计算机科学中的一个强大且基本的抽象概念。序列并不是特定内置类型或抽象数据表示的实例&#xff0c;而是一个包含不同类型数据间共享行为的集合。也就是说&#xff0c;序列有很多种类&…...

几种热管的构造

1、超薄热管构造形式 在实际应用中&#xff0c;超薄热管通常定义为厚度小于2.0mm的平板热管。超薄热管很薄&#xff0c;可紧贴电子元件表面散热&#xff0c;故被广泛应用于移动和可携带电子设备&#xff0c;如智能手机、笔记本电脑和智能手表。用于笔记本电脑和平板电脑的超薄…...

【GitOps】使用Google工具JIB实现本地无需安装容器推送镜像,加速SpringCloud项目开发

文章目录 一、效果展示二、简介三、安装Jib插件1、区分环境2、安装插件一、效果展示 本地是window系统,无docker环境,没有任何runtime,使用jib工具打包镜像并推送完成,用时20秒 二、简介 Jib 是 Google 开发的一款开源工具,旨在帮助 Java 开发者更高效地将 Java 应用程…...

【proteus经典实战】16X192点阵程序

一、简介 6X192点阵程序通常用于表示高分辨率图像或文字&#xff0c;其中16X表示像素阵列的宽度&#xff0c;192表示每个像素阵列中的点阵数&#xff0c;16X192点阵程序需要一定的编程知识和技能才能编写和调试&#xff0c;同时还需要考虑硬件设备的兼容性和性能等因素。 初始…...

小白上手AIGC-基于FC部署stable-diffusion

AIGC AIGC&#xff08;人工智能创造内容&#xff09;作为一种基于人工智能技术生成内容的新型创作模式。打破了过去大家对于AI的理解都是说只能涉足部分领域而无法涉足艺术或者是其他的创作领域的定律&#xff0c;现在的AIGC也能够创作内容了&#xff0c;而不再只是单纯的返回…...

一些指标的学习

1.平均倒数排名&#xff08;MRR&#xff09; 1.定义 MRR 是衡量检索系统返回的结果列表中第一个相关结果位置的指标。具体来说&#xff0c;它是所有查询倒数排名的平均值。 2.计算步骤 对每个查询&#xff0c;找到第一个正确答案在结果列表中的排名 &#x1d445;&#x1d44…...

dledger原理源码分析系列(三)-选主

简介 dledger是openmessaging的一个组件&#xff0c; raft算法实现&#xff0c;用于分布式日志&#xff0c;本系列分析dledger如何实现raft概念&#xff0c;以及dledger在rocketmq的应用 本系列使用dledger v0.40 本文分析dledger的选主 关键词 Raft Openmessaging 心跳/选…...

如何修改PDF文档的作者名称?

要修改一个 PDF 文档的作者名称&#xff0c;你可以按照以下步骤进行操作&#xff1a; 1. **使用 Adobe Acrobat**&#xff08;如果有&#xff09;&#xff1a; - Adobe Acrobat 是一个功能强大的 PDF 编辑工具&#xff0c;支持修改文档属性信息&#xff0c;包括作者名称。打开…...

从笔灵到AI去痕:全方位提升内容创作与学术诚信

内容为王&#xff0c;在内容创作的世界中尤为重要。然而&#xff0c;面对写作时常常感到无从下手&#xff1a;有时缺乏灵感&#xff0c;有时难以表达清楚自己的想法。AI写作助手的出现&#xff0c;为这些问题提供了创新的解决方案&#xff0c;极大地改变了内容创作的过程。 今…...

考试如果出现汉诺塔问题怎么办?

对于这道题来说 就按照测试案例里的数字进行输入 测试案例用100 那这三只鸡的具体最多能有多少只鸡呢&#xff1f; 用总数除以这只鸡的单价>>>>>>>即为这只鸡最多有 >>>>>>>> n / 单价 修改后 >>>>> 不只适…...

导出word模板开发记录

exportWordDocx.js import JSZipUtils from “jszip-utils” import Docxtemplater from “docxtemplater” import {saveAs} from “file-saver” import PizZip from “pizzip” const exportWordDocx (demoUrl, docxData, fileName) > {// 读取并获得模板文件的二进制…...

PHP爬虫类的并发与多线程处理技巧

PHP爬虫类的并发与多线程处理技巧 引言&#xff1a; 随着互联网的快速发展&#xff0c;大量的数据信息存储在各种网站上&#xff0c;获取这些数据已经成为很多业务场景下的需求。而爬虫作为一种自动化获取网络信息的工具&#xff0c;被广泛应用于数据采集、搜索引擎、舆情分析…...

用Python将PowerPoint演示文稿转换到图片和SVG

PowerPoint演示文稿作为展示创意、分享知识和表达观点的重要工具&#xff0c;被广泛应用于教育、商务汇报及个人项目展示等领域。然而&#xff0c;面对不同的分享场景与接收者需求&#xff0c;有时需要我们将PPT内容以图片形式保存与传播。这样能够避免软件兼容性的限制&#x…...

机电公司管理小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;管理员管理&#xff0c;客户管理&#xff0c;公告管理&#xff0c;考勤管理&#xff0c;请假管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;公告&#xff0c;机电零件&…...

SQL中的子查询和CTE(with ....as..)

第一次看到with as 这种类似于python中读文件的写法还是挺疑惑的&#xff0c;其实它是CTE&#xff0c;功能和子查询很类似但又有不同点&#xff0c;在实际应用场景中具有着独特作用。 子查询 子查询是在主查询中的嵌套查询&#xff0c;可以出现在SELECT、FROM、WHERE等子句中…...

Cesium 基本概念:创建实体和相机控制

基本概念 Entity // 创建一个实体 const entity_1 viewer.entities.add({position: new Cesium.Cartesian3(0, 0, 10000000),point: {pixelSize: 10,color: Cesium.Color.BLUE} });// 通过经纬度创建实体 const position Cesium.Cartesian3.fromDegrees(180.0, 0.0); // 创…...

vue使用scrollreveal和animejs实现页面滑动到指定位置后再开始执行动画效果

效果图 效果链接&#xff1a;http://website.livequeen.top 介绍 一、Scrollreveal ScrollReveal 是一个 JavaScript 库&#xff0c;用于在元素进入/离开视口时轻松实现动画效果。 ScrollReveal 官网链接&#xff1a;ScrollReveal 二、animejs animejs是一个好用的动画库…...

在Ubuntu 16.04上安装和配置GitLab的方法

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 简介 GitLab CE&#xff08;Community Edition&#xff09;是一个开源应用程序&#xff0c;主要用于托管 Git 仓库&#xff0c;并提供额…...

STM32的SPI通信

1 SPI协议简介 SPI&#xff08;Serial Peripheral Interface&#xff09;协议是由摩托罗拉公司提出的通信协议&#xff0c;即串行外围设备接口&#xff0c;是一种高速全双工的通信总线。它被广泛地使用在ADC、LCD等设备与MCU间&#xff0c;使用于对通信速率要求较高的场合。 …...

机器学习引领教育革命:智能教育的新时代

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀目录 &#x1f4d2;1. 引言&#x1f4d9;2. 机器学习在教育中的应用&#x1f31e;个性化学习&#x1f319;评估与反馈的智能化⭐教学资源的优…...

6月29日,每日信息差

第一、位于四川省绵阳市的中广核质子治疗装备制造基地正式通过竣工验收&#xff0c;为全球装机数量和治疗患者数量最多的国际领先质子治疗系统全面国产化奠定了坚实基础。质子治疗作为目前全球最尖端的肿瘤放射治疗技术之一&#xff0c;与传统放疗技术相比&#xff0c;质子治疗…...

SpringCloud中复制模块然后粘贴,文件图标缺少蓝色方块

再maven中点击&#xff0b;号&#xff0c;把当前pom文件交给maven管理即可...

JS乌龟吃鸡游戏

代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>乌龟游戏</title><script type"text/javascript">function move(obj){//乌龟图片高度var wuGui_height 67;…...

第十节:学习ConfigurationProperties类来配置pojo实体类参数(自学Spring boot 3.x的第二天)

大家好&#xff0c;我是网创有方 。这节记录下如何使用ConfigurationProperties来实现自动注入配置值。。实现将配置文件里的application.properties的参数赋值给实体类并且打印出来。 第一步&#xff1a;新建一个实体类WechatConfig package cn.wcyf.wcai.config;import org…...

如何学习Node.js

Node.js是一个开源、跨平台的JavaScript运行环境&#xff0c;它允许你在服务器端使用JavaScript。以下是一些步骤和资源&#xff0c;可以帮助你开始学习Node.js&#xff1a; ### 1. 基础知识 首先&#xff0c;确保你熟悉JavaScript语言的基础。Node.js是基于JavaScript的&…...

云计算基础知识

前言&#xff1a; 随着ICT技术的高速发展&#xff0c;企业架构对计算、存储、网络资源的需求更高&#xff0c;急需一种新的架构来承载业务&#xff0c;以获得持续&#xff0c;高速&#xff0c;高效的发展&#xff0c;云计算应运而生。 云计算背景 信息大爆炸时代&#xff1a…...

基于单片机光纤测距系统的设计与实现

摘要 &#xff1a; 光纤由于其频带宽 、 损耗低及抗干扰能力强等优点已被广泛地应用在通信 、 电子及电力方面 &#xff0c; 是我们生产生活中必不可少的媒介。 在实际的光纤实验 、 安装 、 运营和维护工作中 &#xff0c; 一种精准 、 轻便和易操作的光纤测距系统显得尤为重…...

python项目实战——人生重开模拟器

文章目录 1.菜单栏的编写2.玩家确定颜值、体质、智力、家境3.生成性别4.设定角色出生点5.各个年龄段的变化5.1 幼年阶段5.2 青年阶段5.3中年阶段5.4 晚年阶段 6.整体代码 人生重开模拟器是一款文字类小游戏. 玩家可根据提示输入角色的初始属性之后, 就可以开启不同的人生经历. …...

小时候的子弹击中了现在的我-hive进阶:案例解析(第18天)

系列文章目录 一、Hive表操作 二、数据导入和导出 三、分区表 四、官方文档&#xff08;了解&#xff09; 五、分桶表&#xff08;熟悉&#xff09; 六、复杂类型&#xff08;熟悉&#xff09; 七、Hive乱码解决&#xff08;操作。可以不做&#xff0c;不影响&#xff09; 八、…...

电影票房预测管理系统设计

电影票房预测管理系统的开发涉及多个层面的设计&#xff0c;包括但不限于数据收集、数据分析、预测模型构建、用户界面设计和系统集成。以下是一个基本的系统设计框架&#xff1a; 1. 数据收集模块&#xff1a;这是整个系统的基础。需要收集的数据可能包括历史票房数据、上映电…...

正则表达式与Pyhton

一、正则表达式的规则 1、支持普通字符匹配 2、元字符&#xff0c;一个符号匹配一堆字符 \d 匹配数字 \w 匹配数字、字母、下划线 \D \d的取反&#xff0c;除了数字全部匹配 \W \w的取反 [abc] 匹配字母a、b、c [^abc] [abc]的取反&#xf…...

Transformer常见面试题

目录 1.Transformer为何使用多头注意力机制&#xff1f;&#xff08;为什么不使用一个头&#xff09; 2.Transformer为什么Q和K使用不同的权重矩阵生成&#xff0c;为何不能使用同一个值进行自身的点乘&#xff1f; &#xff08;注意和第一个问题的区别&#xff09; 3.Transf…...

Linux——vim的配置文件+异常处理

vim的配置文件&#xff1a; [rootserver ~]# vim /etc/vimrc # 输入以下内容 set nu # 永久设置行号 shell [rootserver ~]# vim /etc/vimrc 或者 vim ~/.vimrc set hlsearch "高亮度反白 set backspace2 "可随时用退格键删除 set autoindent…...

node mySql 实现数据的导入导出,以及导入批量插入的sql语句

node 实现导出, 在导出excel中包含图片&#xff08;附件&#xff09; node 实现导出, 在导出excel中包含图片&#xff08;附件&#xff09;-CSDN博客https://blog.csdn.net/snows_l/article/details/139999392?spm1001.2014.3001.5502 一、效果 如图&#xff1a; 二、导入 …...

Webpack: 底层配置逻辑

概述 Webpack 5 提供了非常强大、灵活的模块打包功能&#xff0c;配合其成熟生态下数量庞大的插件、Loader 资源&#xff0c;已经能够满足大多数前端项目的工程化需求&#xff0c;但代价则是日益复杂、晦涩的使用方法&#xff0c;开发者通常需要根据项目环境、资源类型、编译目…...

数字图像处理期末复习题1

个人名片&#xff1a; &#x1f393;作者简介&#xff1a;嵌入式领域优质创作者&#x1f310;个人主页&#xff1a;妄北y &#x1f4de;个人QQ&#xff1a;2061314755 &#x1f48c;个人邮箱&#xff1a;[mailto:2061314755qq.com] &#x1f4f1;个人微信&#xff1a;Vir2025WB…...

poi-tl 生成 word 文件(插入文字、图片、表格、图表)

文章说明 本篇文章主要通过代码案例的方式&#xff0c;展示 poi-tl 生成 docx 文件的一些常用操作&#xff0c;主要涵盖以下内容 &#xff1a; 插入文本字符&#xff08;含样式、超链接&#xff09;插入图片插入表格引入标签&#xff08;通过可选文字的方式&#xff0c;这种方…...

centos上部署Ollama平台,实现语言大模型本地部署

网上有很多大模型&#xff0c;很多都是远程在线调用ChatGPT的api来实现的&#xff0c;自己本地是没有大模型的&#xff0c;这里和大家分享一个大模型平台&#xff0c;可以实现本地快速部署大模型。 Ollama是一个开源项目&#xff0c;它提供了一个平台和工具集&#xff0c;用于部…...

Java学习 - Redis Redigo简单介绍

Redigo 驱动下载 go get github.com/garyburd/redigo/redis获取redis服务器连接 c, err : redis.Dial("tcp", "127.0.0.1:6379")if err ! nil {panic(err) }defer c.Close()命令使用 v, err : c.Do("SET","hello","world&quo…...

【鸿蒙学习笔记】ArkTS组件 Blank

官方文档&#xff1a;Blank 目录标题...

如何使用Spring Boot进行单元测试

如何使用Spring Boot进行单元测试 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将探讨如何在Spring Boot项目中进行单元测试&#xff0c;确保代码质量…...

2024steam夏促商店打不开、steam活动加载不了解决方法一览

今年的夏促终于开始了!目前可以看到很多精品小游戏在促销列表内&#xff0c;活动正式开启后还不知道又会是怎样的一幅场景。因为每年夏促都会有不少刚高考完的新手加入&#xff0c;遇到常见的steam商店打不开、活动页面不加载等问题不知道怎么解决。所以这里给大家准备了几种常…...

IPC进程通信:QNX

引言 在现代操作系统中&#xff0c;进程间通信&#xff08;IPC&#xff09;机制是实现进程间数据交换和同步的关键技术。IPC允许多个进程共享信息和资源&#xff0c;从而协同工作完成复杂任务。在QNX Neutrino系统中&#xff0c;IPC尤为重要&#xff0c;因为QNX主要面向实时系…...

OpenCV学习之cv2.imshow()函数

OpenCV学习之cv2.imshow()函数 一、简介 cv2.imshow 是 OpenCV 库中用于显示图像的基本函数之一。在图像处理和计算机视觉的过程中&#xff0c;使用该函数可以快速预览处理后的图像&#xff0c;便于调试和结果展示。 二、基本语法 cv2.imshow(WindowName, Imgmat)三、参数说…...

Oracle、MySQL、PostGreSQL、SQL Server-空值

Oracle、MySQL、PostGreSQL、SQL Server-null value 最近几年数据库市场百花齐放&#xff0c;在做跨数据库迁移的数据库选型时&#xff0c;除了性能、稳定、安全、运维、功能、可扩展外&#xff0c;像开发中对于值的处理往往容易被人忽视&#xff0c; 之前写过一篇关于PG区别O…...

python pip详解1

一、简介 pip是python的一个软件包管理工具&#xff0c;同yum&#xff0c;apt作用一致&#xff0c;pip有两种使用方式&#xff1a;pip模块和pip命令&#xff0c;示例如下&#xff1a; python -m pip install package pip install package二、命令行详解 python -m pip --hel…...

Linux常用命令大全(超详细!!!)

文章目录 1.Linux是什么1.1 关于Linux我们主要学习什么1.1 学习Linux常见命令的前置知识 2. Linux常见命令2.1 ls命令2.2 cd命令2.3 pwd命令2.4 touch命令2.5 cat命令2.6 echo命令2.7 vim命令2.8 mkdir 命令2.9 rm命令2.10 cp命令2.11 mv命令2.12 grep命令2.13 ps命令2.14 nets…...

TDD测试驱动开发

为什么需要TDD&#xff1f; 传统开发方式&#xff0c;带来大量的低质量代码&#xff0c;而代码质量带来的问题&#xff1a; 1.在缺陷的泥潭中挣扎 开发长时间投入在缺陷的修复中&#xff0c;修复完依赖测试做长时间的回归测试 2.维护困难&#xff0c;开发缓慢 比如重复代码&am…...

huggingface镜像站

huggingface下载太慢&#xff0c;大模型文件太大。用huggingface_hub镜像。 pip install -U huggingface_hub pip install huggingface-cli export HF_ENDPOINThttps://hf-mirror.com huggingface-cli download --resume-download shenzhi-wang/Llama3-8B-Chinese-Chat --loc…...

Java中如何实现数据库连接池优化?

Java中如何实现数据库连接池优化&#xff1f; 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将深入探讨在Java应用程序中如何实现数据库连接池优化&am…...

c#学习日志用CLI(命令行窗口)创建c#工程

创建Helloworld.Proj和Program.cs两个文件然后运行即可&#xff0c;一种方法是用记事本创建&#xff0c;写入代码&#xff0c;这种比较费劲&#xff0c;主要代码如下 Program.cs中代码如下 System.Console.WriteLine("Hello World!!"); Helloworld.Proj中的代码如…...

Vue 路由传参 query方法 bug 记录

问题描述 vue 路由传参 踩坑 this.$router.push({path: "xxxxxxx",query: {opportunity_id:row.opportunity_id,constructor:row.constructor,},});解决方案&#xff1a; 上述方法传入新页面时&#xff0c;访问的 this.$route.query 会有bug 每一次刷新都会在最后一…...

git-extras

当使用 git-extras 时&#xff0c;除了安装和基本命令之外&#xff0c;了解如何结合常见的 Git 工作流程和实际开发需求会更加有帮助。下面是一个更全面的 git-extras 使用教程&#xff0c;涵盖了安装、常见命令以及实际应用场景的示例。 1. 安装 git-extras 在 macOS 上&…...

2024 最新docker仓库镜像,6月,7月

目前下面的docker仓库镜像源还能使用。 vi /etc/docker/daemon.json添加如下配置{"registry-mirrors": ["https://hub.uuuadc.top", "https://docker.anyhub.us.kg", "https://dockerhub.jobcher.com", "https://dockerhub.icu&…...

sublime如何运行Html文件?

背景&#xff1a; 在sublime上面写了html代码以后&#xff0c;怎么运行html文件来进行debug呢&#xff1f;如果去点击保存的HTML文件&#xff0c;每次这样就会很麻烦&#xff0c;能不能直接在sublime里面点什么就可以直接打开浏览器运行呢&#xff1f;答案是OK的。 1-确认Vie…...

密码学原理精解【5】

这里写目录标题 移位密码概述代码 希尔密码( Z 256 Z_{256} Z256​)待加密长度被3整除待加密长度不一定被3整除加解密文件 移位密码 概述 以 z 26 运算为例 , k 为密钥 加密&#xff1a; e k ( x ) ( x k ) m o d 26 解密&#xff1a; d k ( x ) ( x − k ) m o d 26 以z_{…...

途昂行情,2.5T/26.8万起,2.0T/17.4万起

如果你是SUV车迷,那么大抵上,心里还有一辆终极的大型SUV作为梦想车,试问是不是这样?很多人喜欢宝马X5、也有人喜欢奔驰GLE,可即便现在优惠幅度较高,2.0T的丐版车型也要落地超60万元,可不是随便哪个家庭就能负担的起。但预算在30万内,还是可以选择一辆搭载大V6发动机的中…...

python -【五】数据容器

数据容器 一、列表 列表的循环 name_list [张三, 李四, 王五] print(f类型是&#xff1a;{type(name_list)})# while 遍历列表 count 0 while count < len(name_list):print(fwhile 下标为[{count}] 的内容是[{name_list[count]}])count 1# for 循环 for name in name…...

SAP 生产订单报工函数BAPI_PRODORDCONF_CREATE_TT不返回报错信息

最近财务一直反馈MES报工的数据都没有成本,然后去查看原因发现是财务当月的KP26的价格没有进行维护,导致没有收集到工单的报工成本。 但是在前台操作CO11 报工的时候,系统会给出报错的信息 但是我们在调用函数BAPI_PRODORDCONF_CREATE_TT的时候,系统并没有返回报错的信息…...

解锁Android高效数据传输的秘钥 - Parcelable剖析

作为Android开发者&#xff0c;我们经常需要在不同的组件(Activity、Service等)之间传输数据。这里的"传输"往往不仅仅是简单的数据复制&#xff0c;还可能涉及跨进程的内存复制操作。当传输的数据量较大时&#xff0c;这种操作可能会带来严重的性能问题。而Android系…...

Pi 母公司将开发情感 AI 商业机器人;Meta 科学家:Sora 不是视频生成唯一方向丨RTE 开发者日报 Vol.214

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE&#xff08;Real-Time Engagement&#xff09; 领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「…...

matplotlib ---词云图

词云图是一种直观的方式来展示文本数据&#xff0c;可以体现出一个文本中词频的使用情况&#xff0c;有利于文本分析&#xff0c;通过词频可以抓住一篇文章的重点 本文通过处理一篇关于分析影响洋流流向的文章&#xff0c;分析影响洋流流向的主要因素都有哪些 文本在文末结尾 …...