Python 入门指南(一)(3)

简介: Python 入门指南(一)

Python 入门指南(一)(2)https://developer.aliyun.com/article/1507355

实数

实数,或浮点数,根据 IEEE 754 双精度二进制浮点格式在 Python 中表示,它存储在 64 位信息中,分为三个部分:符号、指数和尾数。

满足你对这种格式的知识渴望:en.wikipedia.org/wiki/Double-precision_floating-point_format

通常,编程语言给程序员提供两种不同的格式:单精度和双精度。前者占用 32 位内存,后者占用 64 位。Python 只支持双精度格式。让我们看一个简单的例子:

>>> pi = 3.1415926536  # how many digits of PI can you remember?
>>> radius = 4.5
>>> area = pi * (radius ** 2)
>>> area
63.617251235400005 

在计算面积时,我在括号中包裹了radius ** 2。尽管这并不是必要的,因为幂运算符的优先级高于乘法运算符,但我认为这样公式读起来更容易。此外,如果你得到的面积稍有不同,不要担心。这可能取决于你的操作系统、Python 的编译方式等等。只要前几位小数正确,你就知道这是正确的结果。

sys.float_info结构序列包含有关浮点数在你的系统上的行为的信息。这是我在我的电脑上看到的:

>>> import sys
>>> sys.float_info
sys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, mant_dig=53, epsilon=2.220446049250313e-16, radix=2, rounds=1)

在这里我们需要考虑一些事情:我们有 64 位来表示浮点数。这意味着我们最多可以用2 ** 64 == 18,446,744,073,709,551,616个位来表示这些数字。看一下浮点数的maxepsilon值,你会意识到不可能表示它们所有。空间不够,所以它们被近似到最接近的可表示的数字。你可能认为只有极大或极小的数字才会受到这个问题的影响。好吧,再想一想,然后在你的控制台上尝试一下:

>>> 0.3 - 0.1 * 3  # this should be 0!!!
-5.551115123125783e-17 

这告诉你什么?它告诉你,双精度数字即使在处理简单的数字如0.10.3时也会受到近似问题的影响。为什么这很重要?如果你处理价格、金融计算或任何不需要近似的数据,这可能是一个大问题。不用担心,Python 给你decimal类型,它不会受到这些问题的影响;我们马上会看到它们。

复数

Python 为你提供了复数支持。如果你不知道复数是什么,它们是可以用形式a + ib表示的数字,其中ab是实数,i(或者如果你是工程师,j)是虚数单位,即*-1的平方根。ab分别被称为数字的实部虚部*。

实际上,你可能不太会用到它们,除非你在编写科学代码。让我们看一个小例子:

>>> c = 3.14 + 2.73j
>>> c.real  # real part
3.14
>>> c.imag  # imaginary part
2.73
>>> c.conjugate()  # conjugate of A + Bj is A - Bj
(3.14-2.73j)
>>> c * 2  # multiplication is allowed
(6.28+5.46j)
>>> c ** 2  # power operation as well
(2.4067000000000007+17.1444j)
>>> d = 1 + 1j  # addition and subtraction as well
>>> c - d
(2.14+1.73j)

分数和小数

让我们以分数和小数结束数字部分的介绍。分数以最简形式包含有理数的分子和分母。让我们看一个快速的例子:

>>> from fractions import Fraction
>>> Fraction(10, 6)  # mad hatter?
Fraction(5, 3)  # notice it's been simplified
>>> Fraction(1, 3) + Fraction(2, 3)  # 1/3 + 2/3 == 3/3 == 1/1
Fraction(1, 1)
>>> f = Fraction(10, 6)
>>> f.numerator
5
>>> f.denominator
3

尽管它们有时可能非常有用,但在商业软件中并不常见。更容易的是,在所有需要精度的情况下使用小数;例如,在科学和金融计算中。

重要的是要记住,任意精度的十进制数当然会带来性能上的代价。每个数字存储的数据量远远大于分数或浮点数,以及它们的处理方式,这使得 Python 解释器在幕后做了更多的工作。另一个有趣的事情是,你可以通过访问decimal.getcontext().prec来获取和设置精度。

让我们看一个十进制数的快速例子:

>>> from decimal import Decimal as D  # rename for brevity
>>> D(3.14)  # pi, from float, so approximation issues
Decimal('3.140000000000000124344978758017532527446746826171875')
>>> D('3.14')  # pi, from a string, so no approximation issues
Decimal('3.14')
>>> D(0.1) * D(3) - D(0.3)  # from float, we still have the issue
Decimal('2.775557561565156540423631668E-17')
>>> D('0.1') * D(3) - D('0.3')  # from string, all perfect
Decimal('0.0')
>>> D('1.4').as_integer_ratio()  # 7/5 = 1.4 (isn't this cool?!)
(7, 5)

请注意,当我们从float构造一个Decimal数字时,它会继承所有可能来自float的近似问题。另一方面,当Decimal没有近似问题时(例如,当我们将intstring表示传递给构造函数时),计算就没有奇怪的行为。在涉及到货币时,请使用小数。

这就结束了我们对内置数值类型的介绍。现在让我们来看看序列。

不可变序列

让我们从不可变序列开始:字符串、元组和字节。

字符串和字节

Python 中的文本数据是通过str对象处理的,更常见的是字符串。它们是Unicode 代码点的不可变序列。Unicode 代码点可以表示一个字符,但也可以有其他含义,比如格式化数据。与其他语言不同,Python 没有char类型,因此一个单个字符只是一个长度为1的字符串。

Unicode 是处理数据的一个很好的方式,应该用于任何应用程序的内部。但是,当涉及到存储文本数据或在网络上传输文本数据时,您可能希望对其进行编码,使用适合您使用的介质的适当编码。编码的结果会产生一个bytes对象,其语法和行为类似于字符串。Python 中的字符串字面量使用单引号、双引号或三引号(单引号或双引号)编写。如果使用三引号构建,字符串可以跨多行。一个例子将澄清这一点:

>>> # 4 ways to make a string
>>> str1 = 'This is a string. We built it with single quotes.'
>>> str2 = "This is also a string, but built with double quotes."
>>> str3 = '''This is built using triple quotes,
... so it can span multiple lines.'''
>>> str4 = """This too
... is a multiline one
... built with triple double-quotes."""
>>> str4  #A
'This too\nis a multiline one\nbuilt with triple double-quotes.'
>>> print(str4)  #B
This too
is a multiline one
built with triple double-quotes.

#A#B中,我们打印str4,首先是隐式地,然后是显式地,使用print函数。一个很好的练习是找出它们为什么不同。您敢挑战吗?(提示:查找str函数。)

字符串,就像任何序列一样,都有一个长度。您可以通过调用len函数来获得这个长度:

>>> len(str1)
49

编码和解码字符串

使用encode/decode方法,我们可以对 Unicode 字符串进行编码和解码字节对象。UTF-8是一种可变长度的字符编码,能够编码所有可能的 Unicode 代码点。它是网络的主要编码。还要注意,通过在字符串声明前添加一个字面量b,我们创建了一个bytes对象:

>>> s = "This is üŋíc0de"  # unicode string: code points
>>> type(s)
<class 'str'>
>>> encoded_s = s.encode('utf-8')  # utf-8 encoded version of s
>>> encoded_s
b'This is \xc3\xbc\xc5\x8b\xc3\xadc0de'  # result: bytes object
>>> type(encoded_s)  # another way to verify it
<class 'bytes'>
>>> encoded_s.decode('utf-8')  # let's revert to the original
'This is üŋíc0de'
>>> bytes_obj = b"A bytes object"  # a bytes object
>>> type(bytes_obj)
<class 'bytes'>

索引和切片字符串

在操作序列时,很常见需要在一个精确的位置(索引)访问它们,或者从中获取一个子序列(切片)。在处理不可变序列时,这两个操作都是只读的。

虽然索引以一种形式出现,即在序列中的任何位置进行基于零的访问,但切片以不同的形式出现。当您获取序列的一个切片时,您可以指定startstop位置以及step。它们用冒号(:)分隔,就像这样:my_sequence[start:stop:step]。所有参数都是可选的,start是包含的,stop是不包含的。最好通过示例来展示,而不是用更多的文字来解释它们:

>>> s = "The trouble is you think you have time."
>>> s[0]  # indexing at position 0, which is the first char
'T'
>>> s[5]  # indexing at position 5, which is the sixth char
'r'
>>> s[:4]  # slicing, we specify only the stop position
'The '
>>> s[4:]  # slicing, we specify only the start position
'trouble is you think you have time.'
>>> s[2:14]  # slicing, both start and stop positions
'e trouble is'
>>> s[2:14:3]  # slicing, start, stop and step (every 3 chars)
'erb '
>>> s[:]  # quick way of making a copy
'The trouble is you think you have time.'

在所有行中,最后一行可能是最有趣的。如果您不指定参数,Python 会为您填充默认值。在这种情况下,start将是字符串的开始,stop将是字符串的结束,step将是默认的1。这是一种简单快捷的方法来获取字符串s的副本(相同的值,但不同的对象)。您能找到一种使用切片获取字符串的反向副本的方法吗(不要查找,自己找到)?

字符串格式化

字符串的一个特性是能够用作模板。有几种不同的格式化字符串的方法,对于所有可能性的完整列表,我鼓励您查阅文档。以下是一些常见的例子:

>>> greet_old = 'Hello %s!'
>>> greet_old % 'Fabrizio'
'Hello Fabrizio!'
>>> greet_positional = 'Hello {} {}!'
>>> greet_positional.format('Fabrizio', 'Romano')
'Hello Fabrizio Romano!' 
>>> greet_positional_idx = 'This is {0}! {1} loves {0}!'
>>> greet_positional_idx.format('Python', 'Fabrizio')
'This is Python! Fabrizio loves Python!'
>>> greet_positional_idx.format('Coffee', 'Fab')
'This is Coffee! Fab loves Coffee!'
 >>> keyword = 'Hello, my name is {name} {last_name}'
>>> keyword.format(name='Fabrizio', last_name='Romano')
'Hello, my name is Fabrizio Romano'

在前面的示例中,您可以看到四种不同的格式化字符串的方式。第一种依赖于%运算符的方式已被弃用,不应再使用。当前,格式化字符串的现代方式是使用format字符串方法。您可以从不同的示例中看到,一对大括号在字符串中充当占位符。当我们调用format时,我们向其提供替换占位符的数据。我们可以在大括号内指定索引(以及更多内容),甚至名称,这意味着我们将不得不使用关键字参数而不是位置参数来调用format

注意通过向format调用提供不同数据来呈现greet_positional_idx的方式不同。显然,我喜欢 Python 和咖啡…大惊喜!

我想向您展示的最后一个功能是 Python 的一个相对较新的添加(版本 3.6),它被称为格式化字符串文字。这个功能非常酷:字符串以f为前缀,并包含用大括号括起来的替换字段。替换字段是在运行时评估的表达式,然后使用format协议进行格式化:

>>> name = 'Fab'
>>> age = 42
>>> f"Hello! My name is {name} and I'm {age}"
"Hello! My name is Fab and I'm 42"
>>> from math import pi
>>> f"No arguing with {pi}, it's irrational..."
"No arguing with 3.141592653589793, it's irrational..."

查看官方文档,了解有关字符串格式和其强大功能的一切。

元组

我们将要看到的最后一个不可变序列类型是元组。元组是任意 Python 对象的序列。在元组中,项目用逗号分隔。它们在 Python 中随处可见,因为它们允许在其他语言中难以复制的模式。有时元组会被隐式使用;例如,一次设置多个变量,或者允许函数返回多个不同的对象(通常函数只返回一个对象,在许多其他语言中),甚至在 Python 控制台中,您可以隐式使用元组以一条指令打印多个元素。我们将为所有这些情况看到示例:

>>> t = ()  # empty tuple
>>> type(t)
<class 'tuple'>
>>> one_element_tuple = (42, )  # you need the comma!
>>> three_elements_tuple = (1, 3, 5)  # braces are optional here
>>> a, b, c = 1, 2, 3  # tuple for multiple assignment
>>> a, b, c  # implicit tuple to print with one instruction
(1, 2, 3)
>>> 3 in three_elements_tuple  # membership test
True

请注意,成员运算符in也可以与列表、字符串、字典以及一般的集合和序列对象一起使用。

请注意,要创建一个只有一个项目的元组,我们需要在项目后面加上逗号。原因是没有逗号,该项目就是自己包裹在括号中,有点像冗余的数学表达式。还要注意,在赋值时,括号是可选的,因此my_tuple = 1, 2, 3my_tuple = (1, 2, 3)是相同的。

元组赋值允许我们做的一件事是一行交换,不需要第三个临时变量。让我们首先看一下更传统的做法:

>>> a, b = 1, 2
>>> c = a  # we need three lines and a temporary var c
>>> a = b
>>> b = c
>>> a, b  # a and b have been swapped
(2, 1)

现在让我们看看我们如何在 Python 中完成它:

>>> a, b = 0, 1
>>> a, b = b, a  # this is the Pythonic way to do it
>>> a, b
(1, 0)

看一下显示 Python 交换两个值的 Pythonic 方式。您还记得我在第一章中写的吗,Python 的初步介绍?Python 程序通常是等效 Java 或 C++代码大小的五分之一到三分之一,并且像一行交换这样的功能有助于实现这一点。Python 是优雅的,这里的优雅也意味着经济。

由于它们是不可变的,元组可以用作字典的键(我们很快会看到这一点)。对我来说,元组是 Python 中最接近数学向量的内置数据。这并不意味着这就是它们被创建的原因。元组通常包含异构元素序列,而另一方面,列表大多数情况下是同构的。此外,元组通常通过解包或索引访问,而列表通常是迭代访问。

可变序列

可变序列与其不可变的姐妹们不同,它们可以在创建后进行更改。Python 中有两种可变序列类型:列表和字节数组。我之前说过字典是 Python 中数据结构的王者。我想这使得列表成为它合法的女王。

列表

Python 列表是可变序列。它们与元组非常相似,但没有不可变性的限制。列表通常用于存储同类对象的集合,但没有什么阻止你存储异类集合。列表可以以许多不同的方式创建。让我们看一个例子:

>>> []  # empty list
[]
>>> list()  # same as []
[]
>>> [1, 2, 3]  # as with tuples, items are comma separated
[1, 2, 3]
>>> [x + 5 for x in [2, 3, 4]]  # Python is magic
[7, 8, 9]
>>> list((1, 3, 5, 7, 9))  # list from a tuple
[1, 3, 5, 7, 9]
>>> list('hello')  # list from a string
['h', 'e', 'l', 'l', 'o']

在前面的例子中,我向你展示了如何使用不同的技术创建列表。我希望你仔细看一下那一行,它说Python is magic,我不指望你在这一点上完全理解它(除非你作弊了,你不是新手!)。这被称为列表推导,是 Python 的一个非常强大的函数特性。

创建列表是好的,但真正的乐趣是在使用它们时,所以让我们看看它们赋予我们的主要方法:

>>> a = [1, 2, 1, 3]
>>> a.append(13)  # we can append anything at the end
>>> a
[1, 2, 1, 3, 13]
>>> a.count(1)  # how many `1` are there in the list?
2
>>> a.extend([5, 7])  # extend the list by another (or sequence)
>>> a
[1, 2, 1, 3, 13, 5, 7]
>>> a.index(13)  # position of `13` in the list (0-based indexing)
4
>>> a.insert(0, 17)  # insert `17` at position 0
>>> a
[17, 1, 2, 1, 3, 13, 5, 7]
>>> a.pop()  # pop (remove and return) last element
7
>>> a.pop(3)  # pop element at position 3
1
>>> a
[17, 1, 2, 3, 13, 5]
>>> a.remove(17)  # remove `17` from the list
>>> a
[1, 2, 3, 13, 5]
>>> a.reverse()  # reverse the order of the elements in the list
>>> a
[5, 13, 3, 2, 1]
>>> a.sort()  # sort the list
>>> a
[1, 2, 3, 5, 13]
>>> a.clear()  # remove all elements from the list
>>> a
[]

前面的代码为你总结了列表的主要方法。我想向你展示它们有多么强大,以extend为例。你可以使用任何序列类型来扩展列表:

>>> a = list('hello')  # makes a list from a string
>>> a
['h', 'e', 'l', 'l', 'o']
>>> a.append(100)  # append 100, heterogeneous type
>>> a
['h', 'e', 'l', 'l', 'o', 100]
>>> a.extend((1, 2, 3))  # extend using tuple
>>> a
['h', 'e', 'l', 'l', 'o', 100, 1, 2, 3]
>>> a.extend('...')  # extend using string
>>> a
['h', 'e', 'l', 'l', 'o', 100, 1, 2, 3, '.', '.', '.']

现在,让我们看看你可以用列表做哪些最常见的操作:

>>> a = [1, 3, 5, 7]
>>> min(a)  # minimum value in the list
1
>>> max(a)  # maximum value in the list
7
>>> sum(a)  # sum of all values in the list
16
>>> len(a)  # number of elements in the list
4
>>> b = [6, 7, 8]
>>> a + b  # `+` with list means concatenation
[1, 3, 5, 7, 6, 7, 8]
>>> a * 2  # `*` has also a special meaning
[1, 3, 5, 7, 1, 3, 5, 7]

前面代码中的最后两行非常有趣,因为它们向我们介绍了一个叫做运算符重载的概念。简而言之,它意味着诸如+-*%等运算符,根据它们所用的上下文,可能代表不同的操作。对两个列表求和没有任何意义,对吧?因此,+号用于将它们连接起来。因此,*号用于根据右操作数将列表连接到自身。

现在,让我们再进一步,看一些更有趣的东西。我想向你展示sorted方法有多么强大,以及在 Python 中实现需要在其他语言中付出很大努力才能实现的结果有多容易:

>>> from operator import itemgetter
>>> a = [(5, 3), (1, 3), (1, 2), (2, -1), (4, 9)]
>>> sorted(a)
[(1, 2), (1, 3), (2, -1), (4, 9), (5, 3)]
>>> sorted(a, key=itemgetter(0))
[(1, 3), (1, 2), (2, -1), (4, 9), (5, 3)]
>>> sorted(a, key=itemgetter(0, 1))
[(1, 2), (1, 3), (2, -1), (4, 9), (5, 3)]
>>> sorted(a, key=itemgetter(1))
[(2, -1), (1, 2), (5, 3), (1, 3), (4, 9)]
>>> sorted(a, key=itemgetter(1), reverse=True)
[(4, 9), (5, 3), (1, 3), (1, 2), (2, -1)]

前面的代码值得解释一下。首先,a是一个元组的列表。这意味着a中的每个元素都是一个元组(准确地说是一个 2 元组)。当我们调用sorted(some_list)时,我们得到了some_list的排序版本。在这种情况下,对 2 元组的排序是通过对元组中的第一个项目进行排序,当第一个项目相同时,再对第二个项目进行排序。你可以在sorted(a)的结果中看到这种行为,得到了[(1, 2), (1, 3), ...]。Python 还给了我们控制排序必须运行的元组元素的能力。注意,当我们指示sorted函数在每个元组的第一个元素上工作(通过key=itemgetter(0))时,结果是不同的:[(1, 3), (1, 2), ...]。排序仅在每个元组的第一个元素上进行(即在位置 0 上)。如果我们想复制简单的sorted(a)调用的默认行为,我们需要使用key=itemgetter(0, 1),这告诉 Python 首先对元组中位置 0 的元素进行排序,然后对位置 1 的元素进行排序。比较结果,你会看到它们是匹配的。

为了完整起见,我包括了一个仅在位置 1 的元素上进行排序的示例,以及相同的示例,但是按相反的顺序。如果你曾经见过 Java 中的排序,我希望你此刻会感到非常印象深刻。

Python 的排序算法非常强大,由 Tim Peters 编写(我们已经见过这个名字,你还记得是在什么时候吗?)。它被称为Timsort,它是mergeinsertion sort的混合体,比大多数其他用于主流编程语言的算法具有更好的时间性能。Timsort 是一种稳定的排序算法,这意味着当多个记录具有相同的键时,它们的原始顺序被保留。我们在sorted(a, key=itemgetter(0))的结果中看到了这一点,它产生了[(1, 3), (1, 2), ...],其中这两个元组的顺序被保留,因为它们在位置 0 上具有相同的值。

字节数组

总结可变序列类型的概述,让我们花几分钟时间来了解bytearray类型。基本上,它们代表了bytes对象的可变版本。它们公开了大多数可变序列的常规方法,以及bytes类型的大多数方法。项目是范围[0, 256)内的整数。

关于间隔,我将使用开/闭范围的标准表示法。一端的方括号表示该值包括在内,而圆括号表示该值不包括在内。通常根据边缘元素的类型来推断粒度,例如,区间[3, 7]表示 3 和 7 之间的所有整数,包括 3 和 7。另一方面,(3, 7)表示 3 和 7 之间的所有整数,不包括 3 和 7(因此为 4、5 和 6)。bytearray类型中的项目是 0 到 256 之间的整数;0 包括在内,256 不包括在内。通常以这种方式表达间隔的一个原因是为了便于编码。如果我们将范围*[a, b)分成N*个连续范围,我们可以轻松地表示原始范围的连接,如下所示:

[a,k[1])+[k[1],k[2])+[k[2],k[3])+…+[k[N-1],b)

中间点(k[i])在一端被排除,在另一端被包括,这样在处理代码中处理间隔时就可以轻松进行连接和拆分。

让我们看一个bytearray类型的快速示例:

>>> bytearray()  # empty bytearray object
bytearray(b'')
>>> bytearray(10)  # zero-filled instance with given length
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
>>> bytearray(range(5)) # bytearray from iterable of integers
bytearray(b'\x00\x01\x02\x03\x04')
>>> name = bytearray(b'Lina')  #A - bytearray from bytes
>>> name.replace(b'L', b'l')
bytearray(b'lina')
>>> name.endswith(b'na')
True
>>> name.upper()
bytearray(b'LINA')
>>> name.count(b'L')
1

如您在前面的代码中所看到的,有几种方法可以创建bytearray对象。它们在许多情况下都很有用;例如,当通过套接字接收数据时,它们消除了在轮询时连接数据的需要,因此它们可能非常方便。在#A行,我创建了一个名为namebytearray,从字节文字b'Lina'中显示了bytearray对象如何公开来自序列和字符串的方法,这非常方便。如果您仔细考虑,它们可以被认为是可变字符串。

集合类型

Python 还提供了两种集合类型,setfrozensetset类型是可变的,而frozenset是不可变的。它们是不可变对象的无序集合。可哈希性是一个特性,允许对象用作字典键和集合成员,正如我们很快将看到的。

从官方文档中:如果对象具有在其生命周期内永远不会更改的哈希值,并且可以与其他对象进行比较,则对象是可哈希的。可哈希性使对象可用作字典键和集合成员,因为这些数据结构在内部使用哈希值。所有 Python 的不可变内置对象都是可哈希的,而可变容器则不是。

比较相等的对象必须具有相同的哈希值。集合非常常用于测试成员资格,因此让我们在以下示例中介绍in运算符:

>>> small_primes = set()  # empty set
>>> small_primes.add(2)  # adding one element at a time
>>> small_primes.add(3)
>>> small_primes.add(5)
>>> small_primes
{2, 3, 5}
>>> small_primes.add(1)  # Look what I've done, 1 is not a prime!
>>> small_primes
{1, 2, 3, 5}
>>> small_primes.remove(1)  # so let's remove it
>>> 3 in small_primes # membership test
True
>>> 4 in small_primes
False
>>> 4 not in small_primes  # negated membership test
True
>>> small_primes.add(3)  # trying to add 3 again
>>> small_primes
{2, 3, 5}  # no change, duplication is not allowed
>>> bigger_primes = set([5, 7, 11, 13])  # faster creation
>>> small_primes | bigger_primes # union operator `|`
{2, 3, 5, 7, 11, 13}
>>> small_primes & bigger_primes  # intersection operator `&`
{5}
>>> small_primes - bigger_primes  # difference operator `-`
{2, 3}

在前面的代码中,您可以看到创建集合的两种不同方法。一种是创建一个空集合,然后逐个添加元素。另一种是使用数字列表作为构造函数的参数来创建集合,这样就可以为我们完成所有工作。当然,您可以从列表或元组(或任何可迭代对象)创建集合,然后随意添加和删除集合成员。

我们将在下一章中查看可迭代对象和迭代。现在,只需知道可迭代对象是可以按方向迭代的对象。

创建集合的另一种方法是简单地使用花括号表示法,如下所示:

>>> small_primes = {2, 3, 5, 5, 3}
>>> small_primes
{2, 3, 5}

请注意,我添加了一些重复以强调结果集不会有任何重复。让我们看一个关于集合类型的不可变对应物frozenset的示例:

>>> small_primes = frozenset([2, 3, 5, 7])
>>> bigger_primes = frozenset([5, 7, 11])
>>> small_primes.add(11)  # we cannot add to a frozenset
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
AttributeError: 'frozenset' object has no attribute 'add'
>>> small_primes.remove(2)  # neither we can remove
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
AttributeError: 'frozenset' object has no attribute 'remove'
>>> small_primes & bigger_primes  # intersect, union, etc. allowed
frozenset({5, 7})

如您所见,frozenset对象在其可变对应物方面相当有限。它们仍然非常有效,用于成员测试、并集、交集和差集操作,以及出于性能原因。

Python 入门指南(一)(4)https://developer.aliyun.com/article/1507360

相关文章
|
3天前
|
Linux 开发工具 Python
初学者从无到有的Python语言如何入门,这份Python学习路线赶紧带走_python 从无到(1)
初学者从无到有的Python语言如何入门,这份Python学习路线赶紧带走_python 从无到(1)
初学者从无到有的Python语言如何入门,这份Python学习路线赶紧带走_python 从无到(1)
|
3天前
|
数据采集 算法 Python
2024年Python最全python基础入门:高阶函数,小米面试编程题
2024年Python最全python基础入门:高阶函数,小米面试编程题
|
3天前
|
存储 数据采集 数据挖掘
真正零基础Python入门:手把手教你从变量和赋值语句学起
真正零基础Python入门:手把手教你从变量和赋值语句学起
|
4天前
|
数据挖掘 数据处理 Python
【Python DataFrame 专栏】Python DataFrame 入门指南:从零开始构建数据表格
【5月更文挑战第19天】本文介绍了Python数据分析中的核心概念——DataFrame,通过导入`pandas`库创建并操作DataFrame。示例展示了如何构建数据字典并转换为DataFrame,以及进行数据选择、添加修改列、计算统计量、筛选和排序等操作。DataFrame适用于处理各种规模的表格数据,是数据分析的得力工具。掌握其基础和应用是数据分析之旅的重要起点。
【Python DataFrame 专栏】Python DataFrame 入门指南:从零开始构建数据表格
|
5天前
|
网络协议 网络架构 Python
Python 网络编程基础:套接字(Sockets)入门与实践
【5月更文挑战第18天】Python网络编程中的套接字是程序间通信的基础,分为TCP和UDP。TCP套接字涉及创建服务器套接字、绑定地址和端口、监听、接受连接及数据交换。UDP套接字则无连接状态。示例展示了TCP服务器和客户端如何使用套接字通信。注意选择唯一地址和端口,处理异常以确保健壮性。学习套接字可为构建网络应用打下基础。
20 7
|
6天前
|
Python
10个python入门小游戏,零基础打通关,就能掌握编程基础_python编写的入门简单小游戏
10个python入门小游戏,零基础打通关,就能掌握编程基础_python编写的入门简单小游戏
|
8天前
|
Python 索引 C语言
Python3从零基础到入门(2)—— 运算符-3
Python3从零基础到入门(2)—— 运算符
|
8天前
|
Python
Python3从零基础到入门(2)—— 运算符-2
Python3从零基础到入门(2)—— 运算符
Python3从零基础到入门(2)—— 运算符-2
|
8天前
|
Python C语言 存储
Python3从零基础到入门(2)—— 运算符-1
Python3从零基础到入门(2)—— 运算符
Python3从零基础到入门(2)—— 运算符-1
|
8天前
|
存储 C语言 Python