{ "cells": [ { "cell_type": "markdown", "metadata": { "toc-hr-collapsed": false }, "source": [ "# 数据容器" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "在 Python 中,有个**数据容器**(Container)的概念。\n", "\n", "其中包括**字符串**、由 `range()` 函数生成的**等差数列**、**列表**(List)、**元组**(Tuple)、**集合**(Set)、**字典**(Dictionary)。\n", "\n", "这些容器,各有各的用处。其中又分为*可变*容器(Mutable)和*不可变*容器(Immutable)。可变的有列表、集合、字典;不可变的有字符串、`range()` 生成的等差数列、元组。集合,又分为 *Set* 和 *Frozen Set*;其中,Set 是*可变的*,Frozen Set 是*不可变的*。\n", "\n", "字符串、由 `range()` 函数生成的等差数列、列表、元组是**有序类型**(Sequence Type),而集合与字典是*无序*的。\n", "\n", "![](images/python-containers-final.png)\n", "\n", "另外,集合没有*重合*元素。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 迭代(Iterate)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "数据容器里的元素是可以被**迭代的**(Iterable),它们其中包含的元素,可以被逐个访问,以便被处理。\n", "\n", "对于数据容器,有一个操作符,`in`,用来判断某个元素是否属于某个容器。\n", "\n", "由于数据容器的可迭代性,再加上这个操作符 `in`,在 Python 语言里写循环格外容易且方便(以字符串这个字符的容器作为例子):" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "P\n", "y\n", "t\n", "h\n", "o\n", "n\n" ] } ], "source": [ "for c in 'Python':\n", " print(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "在 Python 出现之前,想要完成这样一个访问字符串中的每一个字符的循环,大抵上应该是这样的(比如 C 语言):\n", "\n", "``` C\n", "# Written in C\n", "char *string;\n", "\n", "scanf(\"%s\",string); \n", "int i=strlen(string);\n", "int k = 0;\n", "while(k * 拼接:`+`(与字符串不一样的地方是,不能用空格 `' '` 了)\n", "> * 复制:`*`\n", "> * 逻辑运算:`in` 和 `not in`,`<`、`<=`、`>`、`>=`、`!=`、`==`\n", "\n", "而后两个列表也和两个字符串一样,可以被比较,即,可以进行逻辑运算;比较方式也跟字符串一样,从两个列表各自的第一个元素开始逐个比较,“一旦决出胜负马上停止”:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2, 3, 4, 5, 6, 4, 5, 6, 4, 5, 6]" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "True" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "False" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.core.interactiveshell import InteractiveShell\n", "InteractiveShell.ast_node_interactivity = \"all\"\n", "\n", "a_list = [1, 2, 3]\n", "b_list = [4, 5, 6]\n", "c_list = a_list + b_list * 3\n", "c_list\n", "7 not in c_list\n", "a_list > b_list" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 根据索引提取列表元素" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "列表当然也可以根据索引操作,但由于列表是可变序列,所以,不仅可以提取,还可以删除,甚至替换。" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[77, 66, 79]\n", "[77, 66, 79, 'L', 'Z', 'R', 77, 66, 79, 77, 66, 79]\n", "\n", "L\n", "[77, 66, 79, 'L', 'Z', 'R', 77, 66, 79, 77, 66, 79]\n", "['R', 77, 66, 79, 77, 66, 79]\n", "[77, 66, 79]\n", "[79, 'L', 'Z', 'R']\n", "\n", "[77, 66, 79, 'Z', 'R', 77, 66, 79, 77, 66, 79]\n", "[77, 66, 79, 'Z', 'R', 77, 66, 79]\n", "\n", "[77, 'a', 79, 2, 'R', 77, 66, 79]\n" ] } ], "source": [ "import random\n", "n = 3 \n", "a_list = [random.randrange(65, 91) for i in range(n)]\n", "b_list = [chr(random.randrange(65, 91)) for i in range(n)]\n", "print(a_list)\n", "c_list = a_list + b_list + a_list * 2\n", "print(c_list)\n", "\n", "print()\n", "# 根据索引提取(Slicing)\n", "print(c_list[3]) # 返回索引值为 3 的元素值\n", "print(c_list[:]) # 相当于 c_list,返回整个列表\n", "print(c_list[5:]) # 从索引为 5 的值开始直到末尾\n", "print(c_list[:3]) # 从索引 0 开始,直到索引 3 之前(不包括 3)\n", "print(c_list[2:6]) # 从索引 2 开始,直到索引 6 之前(不包括 6)\n", "\n", "print()\n", "# 根据索引删除\n", "del c_list[3]\n", "print(c_list) # del 是个命令,del c_list[3] 是一个语句;不能这么写:print(del c_list[3])\n", "del c_list[5:8] \n", "print(c_list)\n", "\n", "print()\n", "# 根据索引替换\n", "c_list[1:5:2] = ['a', 2] # s[start:stop:step] = t,跟 range 的三个参数类似;\n", " # len(t) = len([start:stop:step]) 必须为真\n", "print(c_list)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "需要注意的地方是:**列表**(List)是可变序列,而**字符串**(str)是不可变序列,所以,对字符串来说,虽然也可以根据索引提取,但没办法根据索引删除或者替换。" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tho\n" ] }, { "ename": "TypeError", "evalue": "'str' object doesn't support item deletion", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0ms\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'Python'\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ms\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0;32mdel\u001b[0m \u001b[0ms\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;31m# 这一句会报错\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mTypeError\u001b[0m: 'str' object doesn't support item deletion" ] } ], "source": [ "s = 'Python'[2:5]\n", "print(s)\n", "del s[2] # 这一句会报错" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "之前提到过:\n", "\n", "> 字符串常量(String Literal)是不可变有序容器,所以,虽然字符串也有一些 Methods 可用,但那些 Methods 都不改变它们自身,而是在操作后返回一个值给另外一个变量。\n", "\n", "而对于列表这种*可变容器*,我们可以对它进行操作,结果是*它本身被改变*了。" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Python\n", "['P', 'y', 't', 'h', 'o', 'n']\n", "['P', 'y', 'h', 'o', 'n']\n" ] } ], "source": [ "s = 'Python'\n", "L = list(s)\n", "print(s)\n", "print(L)\n", "del L[2]\n", "print(L) # 用 del 对 L 操作之后,L 本身少了 1 个元素" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 列表可用的内建函数" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "列表和字符串都是容器,它们可使用的内建函数也其实都是一样的:\n", "\n", "> * `len()`\n", "> * `max()`\n", "> * `min()`" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[89, 84, 85]\n", "['X', 'B', 'X']\n", "[89, 84, 85, 'X', 'B', 'X', 89, 84, 85, 89, 84, 85]\n", "[89, 84, 85, 89, 84, 85, 89, 84, 85]\n", "12\n", "X\n", "B\n", "False\n" ] } ], "source": [ "import random\n", "n = 3 \n", "\n", "# 生成 3 个随机数,构成一个列表\n", "a_list = [random.randrange(65, 91) for i in range(n)]\n", "b_list = [chr(random.randrange(65, 91)) for i in range(n)]\n", "print(a_list)\n", "print(b_list)\n", "\n", "# 列表可以使用操作符 + 和*\n", "c_list = a_list + b_list + a_list * 2\n", "print(c_list)\n", "\n", "a_list *= 3\n", "print(a_list)\n", "\n", "# 内建函数操作 len()、max()、min()\n", "print(len(c_list))\n", "print(max(b_list)) # 内建函数内部做了异常处理,可以在字符之间或者数字之间进行比较 —— 初学者最讨厌这种事情了……\n", "print(min(b_list)) # 注意,max() 和 min() 应用的是 b_list, len() 应用的是 c_list —— 请自行找到对应的 list 进行分析。\n", "\n", "print('X' not in b_list)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Methods" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "字符串常量和 range() 都是不可变的(Immutable);而列表则是**可变类型**(Mutable type),所以,它最起码可以被排序 —— 使用 `sort()` Method:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a_list comprehends 10 random numbers:\n", " [98, 9, 95, 15, 80, 70, 98, 82, 88, 46]\n", "the list sorted:\n", " [9, 15, 46, 70, 80, 82, 88, 95, 98, 98]\n", "the list sorted reversely:\n", " [98, 98, 95, 88, 82, 80, 70, 46, 15, 9]\n" ] } ], "source": [ "import random\n", "n = 10 \n", "a_list = [random.randrange(1, 100) for i in range(n)]\n", "print(f'a_list comprehends {len(a_list)} random numbers:\\n', a_list)\n", "\n", "a_list.sort()\n", "print('the list sorted:\\n', a_list)\n", "\n", "a_list.sort(reverse=True) #reverse 参数,默认是 False\n", "print('the list sorted reversely:\\n', a_list)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "如果列表中的元素全都是由字符串构成的,当然也可以排序:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a_list comprehends 10 random string elements:\n", " ['B', 'U', 'H', 'D', 'C', 'V', 'V', 'Q', 'U', 'P']\n", "the list sorted:\n", " ['B', 'C', 'D', 'H', 'P', 'Q', 'U', 'U', 'V', 'V']\n", "the list sorted reversely:\n", " ['V', 'V', 'U', 'U', 'Q', 'P', 'H', 'D', 'C', 'B']\n", "\n", "b_list comprehends 10 random string elements:\n", " ['Nl', 'Mh', 'Ta', 'By', 'Ul', 'Nc', 'Gu', 'Rp', 'Pv', 'Bu']\n", "the sorted:\n", " ['Bu', 'By', 'Gu', 'Mh', 'Nc', 'Nl', 'Pv', 'Rp', 'Ta', 'Ul']\n", "the sorted reversely:\n", " ['Ul', 'Ta', 'Rp', 'Pv', 'Nl', 'Nc', 'Mh', 'Gu', 'By', 'Bu']\n" ] } ], "source": [ "import random\n", "n = 10 \n", "\n", "a_list = [chr(random.randrange(65, 91)) for i in range(n)]\n", "# chr() 函数会返回指定 ascii 码的字符,ord('A') 是 65\n", "print(f'a_list comprehends {len(a_list)} random string elements:\\n', a_list)\n", "\n", "a_list.sort()\n", "print('the list sorted:\\n', a_list)\n", "\n", "a_list.sort(reverse=True) #reverse 参数,默认是 False\n", "print('the list sorted reversely:\\n', a_list)\n", "\n", "print()\n", "\n", "b_list = [chr(random.randrange(65, 91)) +\\\n", " chr(random.randrange(97, 123))\\\n", " for i in range(n)]\n", "# 可以在行末加上 \\ 符号,表示 “该行未完待续……”\n", "\n", "print(f'b_list comprehends {len(b_list)} random string elements:\\n', b_list)\n", "\n", "b_list.sort()\n", "print('the sorted:\\n', b_list)\n", "\n", "b_list.sort(key=str.lower, reverse=True) \n", "# key 参数,默认是 None\n", "# key=str.lower 的意思是,在比较的时候,先全都转换成小写再比较……\n", "# —— 但并不改变原有值\n", "print('the sorted reversely:\\n', b_list)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**注意**:不能乱比较…… 被比较的元素应该是同一类型 —— 所以,不是由同一种数据类型元素构成的列表,不能使用 `sort()` Method。下面的代码会报错:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "'<' not supported between instances of 'str' and 'int'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0ma_list\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'a'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'c'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0ma_list\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0ma_list\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msort\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# 这一句会报错\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mTypeError\u001b[0m: '<' not supported between instances of 'str' and 'int'" ] } ], "source": [ "a_list = [1, 'a', 'c']\n", "a_list = a_list.sort() # 这一句会报错" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**可变序列**还有一系列可用的 **Methods**:`a.append()`,`a.clear()`,`a.copy()`,`a.extend(t)`,`a.insert(i,x)`,`a.pop([i])`,`a.remove(x)`,`a.reverse()`……" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[90, 88, 73]\n", "[90, 88, 73, 'T', 'N', 'Y', 90, 88, 73, 90, 88, 73]\n", "[90, 88, 73, 'T', 'N', 'Y', 90, 88, 73, 90, 88, 73, '100']\n", "\n", "[90, 88, 73]\n", "[]\n", "\n", "[90, 88, 73, 'T', 'N', 'Y', 90, 88, 73, 90, 88, 73, '100']\n", "[90, 88, 73, 'T', 'N', 'Y', 73, 90, 88, 73, '100']\n", "[90, 88, 73, 'T', 'N', 'Y', 90, 88, 73, 90, 88, 73, '100']\n", "\n", "[90, 88, 73, 'T', 'N', 'Y', 88, 73, '100']\n", "[90, 88, 73, 'T', 'N', 'Y', 88, 73, '100']\n", "\n", "[]\n", "[90, 88, 73, 'T', 'N', 'Y', 90, 88, 73, 90, 88, 73, '100']\n", "\n", "[90, 88, 73, 'T', 'N', 'Y', 90, 88, 73, 90, 88, 73, '100']\n", "[90, 'example', 88, 'example', 73, 'T', 'N', 'Y', 90, 88, 73, 90, 88, 73, '100']\n", "\n", "[90, 'example', 88, 'example', 73, 'T', 'N', 'Y', 90, 88, 73, 90, 88, 73, '100']\n", "['100', 73, 88, 90, 73, 88, 90, 'Y', 'N', 'T', 73, 'example', 88, 'example', 90]\n", "None\n" ] } ], "source": [ "import random\n", "n = 3 \n", "a_list = [random.randrange(65, 91) for i in range(n)]\n", "b_list = [chr(random.randrange(65, 91)) for i in range(n)]\n", "print(a_list)\n", "c_list = a_list + b_list + a_list * 2\n", "print(c_list)\n", "\n", "# 在末尾追加一个元素\n", "c_list.append('100')\n", "print(c_list)\n", "\n", "# 清空序列\n", "print()\n", "print(a_list)\n", "a_list.clear()\n", "print(a_list)\n", "\n", "print()\n", "# 拷贝一个列表\n", "d_list = c_list.copy()\n", "print(d_list)\n", "del d_list[6:8]\n", "print(d_list)\n", "print(c_list) # 对一个拷贝操作,不会更改 “原件”\n", "\n", "print()\n", "# 演示拷贝 .copy() 与赋值 = 的不同\n", "e_list = d_list\n", "del e_list[6:8]\n", "print(e_list)\n", "print(d_list) # 对 e_list 操作,相等于对 d_list 操作\n", "\n", "# 在末尾追加一个列表\n", "print()\n", "print(a_list)\n", "a_list.extend(c_list) # 相当于 a_list += c_list\n", "print(a_list)\n", "\n", "# 在某索引位置插入一个元素\n", "print()\n", "print(a_list)\n", "a_list.insert(1, 'example') # 在索引 1 的位置插入 'example'\n", "a_list.insert(3, 'example') # 在索引 3 的位置插入 'example';\n", "print(a_list)\n", "\n", "# 排序\n", "\n", "# a_list.sort() 这一句会出错,因为当前列表中的元素,是 int 和 str 混合的。\n", "\n", "print()\n", "print(a_list)\n", "a_list.reverse()\n", "print(a_list)\n", "x = a_list.reverse() # reverse() 只对当前序列操作,并不返回一个逆序列表;返回值是 None\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "有一个命令、两个 Methods 与删除单个元素相关联,`del`,`a.pop([i])`,`a.remove(x)`,请注意它们之间的区别。" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[88, 84, 69]\n", "\n", "\n", "[88, 'example', 84, 69]\n", "[88, 84, 69]\n", "\n", "[88, 84, 69]\n", "[88, 84]\n", "69\n", "\n", "[88, 84, 'example', 'example']\n", "[88, 84, 'example']\n", "\n", "None\n", "[88, 84]\n" ] } ], "source": [ "import random\n", "n = 3 \n", "a_list = [random.randrange(65, 91) for i in range(n)]\n", "print(a_list)\n", "\n", "# 插入\n", "print()\n", "a_list.insert(1, 'example') # 在索引 1 的位置插入 'example'\n", "\n", "# 删除\n", "print()\n", "print(a_list)\n", "a_list.remove('example') # 去除 'example' 这个元素,如果有多个 'example',只删除第一个\n", "print(a_list)\n", "\n", "# pop() 删除并返回被删除的值\n", "\n", "print()\n", "print(a_list)\n", "p = a_list.pop(2) # 去除索引为 2 的元素,且返回元素的值,赋值给 p\n", "print(a_list)\n", "print(p)\n", "\n", "# pop() 与 del,或者 remove() 的区别\n", "print()\n", "a_list.insert(2, 'example')\n", "a_list.insert(2, 'example')\n", "print(a_list)\n", "del a_list[2]\n", "print(a_list)\n", "\n", "print()\n", "print(a_list.remove('example')) # a_list.remove() 这个 Method 的返回值是 None\n", "print(a_list)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 小结" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "看起来是个新概念,例子全部读完也很是要花上一段时间,然而,从操作上来看,操作列表和操作字符串的差异并不大,重点在于一个是 Immutable,另外一个是 Mutable,所以,例如像 `a.sort()`,`a.remove()` 这样的事,列表能做,字符串不能做 —— 字符串也可以排序,但那是排序之后返回给另外一个变量;而列表可以直接改变自身……\n", "\n", "而整理成表格之后呢,理解与记忆真的是零压力:\n", "\n", "![](images/list-concepts.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 元组(Tuple)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "在完整掌握列表的创建与操作之后,再理解元组(Tuple)就容易了,因为它们之间的主要区别只有两个:\n", "\n", "> * List 是*可变*有序容器,Tuple 是*不可变*有序容器。\n", "> * List 用*方括号*标识 `[]`,Tuple 用*圆括号* 标识 `()`。\n", "\n", "创建一个元组的时候,用圆括号:\n", "\n", "```python\n", "a = ()\n", "``` \n", "\n", "这样就创建了一个空元组。\n", "\n", "多个元素之间,用 `,` 分离。\n", "\n", "创建一个含多个元素的元组,可以省略这个括号。" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(1, 2, 3)\n", "(1, 2, 3)\n" ] }, { "data": { "text/plain": [ "True" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = 1, 2, 3 # 不建议这种写法\n", "b = (1, 2, 3) # 在创建元组的时候建议永远不省略圆括号……\n", "print(a)\n", "print(b)\n", "a == b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**注意**:创建单个元素的元组,无论是否使用圆括号,在那唯一的元素后面一定要*补上一个逗号* `,`:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(2,)" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "2" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "2" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "int" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "(2,)" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "True" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.core.interactiveshell import InteractiveShell\n", "InteractiveShell.ast_node_interactivity = \"all\"\n", "\n", "a = 2, # 注意这个末尾的逗号 , 它使得 a 变量被定义为一个元组,而不是数字\n", "a\n", "\n", "b = 2 # 整数,赋值\n", "b\n", "\n", "c = (2) # 不是元组\n", "c\n", "type(c) # 还是 int\n", "\n", "d = (2,) # 这才是元组\n", "d\n", "a == d" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "元组是不可变序列,所以,你没办法从里面删除元素。\n", "\n", "但是,你可以在末尾追加元素。所以,严格意义上,对元组来讲,“不可变” 的意思是说,“**当前已有部分不可变**”……" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(1,)\n", "4593032496\n", "(1, 3, 5)\n", "4592468976\n" ] } ], "source": [ "a = 1, \n", "print(a)\n", "print(id(a))\n", "a += 3, 5\n", "print(a)\n", "print(id(a)) # id 并不相同 —— 实际上是在内存中另外新创建了一个元组……" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "初学者总是很好奇 List 和 Tuple 的区别。首先是使用场景,在将来需要更改的时候,创建 List\n", ";在将来不需要更改的时候,创建 Tuple。其次,从计算机的角度来看,Tuple 相对于 List 占用更小的内存。" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "48" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "80024" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "90088" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.core.interactiveshell import InteractiveShell\n", "InteractiveShell.ast_node_interactivity = \"all\"\n", "\n", "n = 10000 #@param {type:\"number\"}\n", "a = range(n)\n", "b = tuple(a) # 把 a 转换成元组\n", "c = list(a) # 把 a 转换成列表\n", "a.__sizeof__()\n", "b.__sizeof__()\n", "c.__sizeof__()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "等你了解了 Tuple 的标注方式,你就会发现,`range()` 函数返回的等差数列就是一个 Tuple —— `range(6)` 就相当于 `(0, 1, 2, 3, 4, 5)`。" ] }, { "cell_type": "markdown", "metadata": { "toc-hr-collapsed": true }, "source": [ "## 集合(Set)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**集合**(Set)这个容器类型与列表不同的地方在于,首先它*不包含重合元素*,其次它是*无序*的;进而,集合又分为两种,Set,*可变的*,Frozen Set,*不可变的*。\n", "\n", "创建一个集合,用**花括号** `{}` 把元素括起来,用 `,` 把元素隔开:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{2, 3, 5, 7, 11, 13, 17}" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "primes = {2, 3, 5, 7, 11, 13, 17}\n", "primes" ] }, { "cell_type": "markdown", "metadata": { "toc-hr-collapsed": true }, "source": [ "### 创建" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "注意:创建空集合的时候,必须用 `set()`,而不能用 `{}`:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "dict" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "set" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.core.interactiveshell import InteractiveShell\n", "InteractiveShell.ast_node_interactivity = \"all\"\n", "\n", "a = {} # 注意这样创建的是一个 dict(字典),而不是 set 集合\n", "b = set() # 这样创建的才是空集合\n", "type(a)\n", "type(b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "也可以将序列数据转换(Casting)为集合。转换后,返回的是一个已**去重**的集合。" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'a', 'b', 'c', 'd', 'e', 'f'}" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "{1, 2, 3}" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "{'a', 'b', 'e'}" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.core.interactiveshell import InteractiveShell\n", "InteractiveShell.ast_node_interactivity = \"all\"\n", "\n", "a = \"abcabcdeabcdbcdef\"\n", "b = range(10)\n", "c = [1, 2, 2, 3, 3, 1]\n", "d = ('a', 'b', 'e', 'b', 'a')\n", "set(a)\n", "set(b)\n", "set(c)\n", "set(d)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Set 当然也可以进行 *Comprehension*:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'d', 'e', 'f'}" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = \"abcabcdeabcdbcdef\"\n", "b = {x for x in a if x not in 'abc'}\n", "b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 操作" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "将序列类型数据转换成 Set,就等于**去重**。当然,也可以用 `in` 来判断某个元素是否属于这个集合。`len()`、`max()`、`min()`,也都可以用来操作 Set,但 `del` 却不行 —— 因为 Set 中的元素没有索引(它不是有序容器)。从 Set 里删除元素,得用 `set.remove(elem)`;而 Frozen Set 是不可变的,所以不能用 `set.remove(elem)` 操作。\n", "\n", "对于集合,有相应的操作符可以对它们进行集合运算:\n", "\n", "> * 并集:`|`\n", "> * 交集:`&`\n", "> * 差集:`-`\n", "> * 对称差集:`^`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "之前用 `set('abcabcdeabcdbcdef')` 作为简单例子还凑合能用;但这样对读者无意义的集合,无助于进一步的理解。\n", "\n", "事实上,每种数据结构(Data Structures —— 在这一章里,我们一直用的概念是 “容器”,其实是指同一事物的两种称呼)都有自己的应用场景。比如,当我们需要管理很多用户时,集合就可以派上很大用场。\n", "\n", "假定两个集合中有些人是 admins,有些人是 moderators:\n", "\n", "```python\n", "admins = {'Moose', 'Joker', 'Joker'}\n", "moderators = {'Ann', 'Chris', 'Jane', 'Moose', 'Zero'}\n", "```\n", "\n", "那么:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'Joker', 'Moose'}" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "True" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "False" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "{'Ann', 'Chris', 'Jane', 'Joker', 'Moose', 'Zero'}" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "{'Moose'}" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "{'Joker'}" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "{'Ann', 'Chris', 'Jane', 'Joker', 'Zero'}" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "admins = {'Moose', 'Joker', 'Joker'}\n", "moderators = {'Ann', 'Chris', 'Jane', 'Moose', 'Zero'}\n", "\n", "admins # 去重自动完成\n", "'Joker' in admins # Joker 是否是 admins?\n", "'Joker' in moderators # Joker 是否是 moderator?\n", "admins | moderators # admins、moderator,或者身兼两职的,即,两个角色中的所有人 in admins or moderators or both\n", "admins & moderators # 既是 admins 又是 moderator 的都有谁?in both admins and moderators\n", "admins - moderators # 是 admins 但不是 moderator 的都有谁?in admins but not in moderators\n", "admins ^ moderators # admins 和 moderator 中不是身兼两职的都有谁?in admins or moderator but not both" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# 这个 cell 集合运算图示需要安装 matplotlib 和 matplotlib-venn\n", "# !pip install matplotlib\n", "# !pip install matplotlib-venn\n", "import matplotlib.pyplot as plt\n", "from matplotlib_venn import venn2\n", "\n", "admins = {'Moose', 'Joker', 'Joker'}\n", "moderators = {'Ann', 'Chris', 'Jane', 'Moose', 'Zero'}\n", "\n", "v = venn2(subsets=(admins, moderators), set_labels=('admins', 'moderators'))\n", "v.get_label_by_id('11').set_text('\\n'.join(admins & moderators))\n", "v.get_label_by_id('10').set_text('\\n'.join(admins - moderators))\n", "v.get_label_by_id('01').set_text('\\n'.join(moderators - admins))\n", "\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以上的操作符,都有另外一个版本,即,用 Set 这个类的 Methods 完成。\n", "\n", "| 意义 | 操作符 | Methods | Methods 相当于 |\n", "| :------: | :----: | :---------------------: | :--: |\n", "| 并集 | | | `set.union(*others)` | set | other | ... |\n", "| 交集 | `&` | `set.intersection(*others)` | `set & other & ...` |\n", "| 差集 | `-` | `set.difference(*others)` | `set - other - ...` |\n", "| 对称差集 | `^` | `set.symmetric_difference(other)` | `set ^ other` |\n", "\n", "注意,并集、交集、差集的 Methods,可以接收多个集合作为参数 `(*other)`,但对称差集 Method 只接收一个参数 `(other)`。\n", "\n", "对于集合,推荐更多使用 Methods 而不是操作符的主要原因是:更易读 —— 对人来说,因为有意义、有用处的代码终将需要人去维护。" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'Chris', 'Jane', 'Joker', 'Moose', 'Zero'}" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "{'Moose'}" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "{'Joker'}" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "{'Chris', 'Jane', 'Joker', 'Zero'}" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.core.interactiveshell import InteractiveShell\n", "InteractiveShell.ast_node_interactivity = \"all\"\n", "\n", "admins = {'Moose', 'Joker', 'Joker'}\n", "moderators = {'Chris', 'Moose', 'Jane', 'Zero'}\n", "\n", "admins.union(moderators)\n", "admins.intersection(moderators)\n", "admins.difference(moderators)\n", "admins.symmetric_difference(moderators)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 逻辑运算" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "两个集合之间可以进行逻辑比较,返回布尔值。\n", "\n", "**set** `==` **other**\n", "> `True`: set 与 other 相同\n", "\n", "**set** `!=` **other**\n", "> `True`: set 与 other 不同\n", "\n", "**isdisjoint**(_other_)\n", "> `True`: set 与 other 非重合;即,`set & other == None`\n", "\n", "**issubset**(_other_),**set** `<=` **other**\n", "> `True`: set 是 other 的子集\n", "\n", "**set** `<` **other**\n", "> `True`: set 是 other 的真子集,相当于 `set <= other && set != other`\n", "\n", "**issuperset**(_other_),**set** `>=` **other**\n", "> `True`: set 是 other 的超集\n", "\n", "**set** `>` **other**\n", "> `True`: set 是 other 的真超集,相当于 `set >= other && set != other`" ] }, { "cell_type": "markdown", "metadata": { "toc-hr-collapsed": true }, "source": [ "### 更新" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "对于集合,有以下更新它自身的 Method:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**add**(*elem*)\n", "> 把 elem 加入集合\n", "\n", "**remove**(*elem*)\n", "> 从集合中删除 elem;如果集合中不包含该 elem,会产生 KeyError 错误。\n", "\n", "**discard**(*elem*)\n", "> 如果该元素存在于集合中,删除它。\n", "\n", "**pop**()\n", "> 从集合中随机删除一个元素,并返回删除的元素的值,针对空集合做此操作会产生 KeyError 错误。\n", "\n", "**clear**()\n", "从集合中删除所有元素。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**set.update**(*_others_),相当于 `set |= other | ...`\n", "> 更新 set, 加入 others 中的所有元素;\n", "\n", "**set.intersection_update**(*_others_),相当于 `set &= other & ...`\n", "> 更新 set, 保留同时存在于 set 和所有 others 之中的元素;\n", "\n", "**set.difference_update**(*_others_),相当于 `set -= other | ...`\n", "> 更新 set, 删除所有在 others 中存在的元素;\n", "\n", "**set.symmetric_difference_update**(_other_),相当于 `set ^= other`\n", "> 更新 set, 只保留存在于 set 或 other 中的元素,但不保留同时存在于 set 和 other 中的元素;**注意**,该 Method *只接收一个参数*。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 冻结集合" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "还有一种集合,叫做冻结集合(Frozen Set),Frozen Set 之于 Set,正如 Tuple 之于 List,前者是不可变容器(Immutable),后者是可变容器(Mutable),无非是为了节省内存使用而设计的类别。\n", "\n", "有空去看看这个链接就可以了:\n", "\n", "> https://docs.python.org/3/library/stdtypes.html#frozenset" ] }, { "cell_type": "markdown", "metadata": { "toc-hr-collapsed": true }, "source": [ "## 字典(Dictionary)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Map 是容器中的单独一类,**映射**(Map)容器。映射容器只有一种,叫做**字典**(Dictionary)。先看一个例子:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "phonebook = {'ann':6575, 'bob':8982, 'joe':2598, 'zoe':1225}\n", "phonebook" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "字典里的每个元素,由两部分组成,_key_(键)和 _value_(值),二者由一个冒号连接。\n", "\n", "比如,`'ann':6575` 这个字典元素,_key_ 是 `'ann'`,_value_ 是 `6575`。\n", "\n", "字典直接使用 _key_ 作为索引,并映射到与它匹配的 _value_:" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "8982" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "phonebook = {'ann':6575, 'bob':8982, 'joe':2598, 'zoe':1225}\n", "phonebook['bob']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "在同一个字典里,_key_ 都是唯一的。当创建字典的时候,如果其中有重复的 _key_ 的话,就跟 Set 那样会 “**自动去重**” —— 保留的是众多重复的 _key_ 中的最后一个 _key:value_(或者说,最后一个 _key:value_ “之前那个 _key_ 的 _value_ 被**更新**了”)。字典这个数据类型之所以叫做 Map(映射),是因为字典里的 _key_ 都映射且只映射一个对应的 _value_。" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'ann': 6585, 'bob': 8982, 'joe': 2598, 'zoe': 1225}" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "phonebook = {'ann':6575, 'bob':8982, 'joe':2598, 'zoe':1225, 'ann':6585}\n", "phonebook" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "在已经了解如何操作列表之后,再去理解字典的操作,其实没什么难度,无非就是字典多了几个 Methods。\n", "\n", "提蓄一下自己的耐心,把下面的若干行代码都仔细阅读一下,猜一猜输出结果都是什么?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 字典的生成" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{}" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "{'a': 1, 'b': 2, 'c': 3}" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.core.interactiveshell import InteractiveShell\n", "InteractiveShell.ast_node_interactivity = \"all\"\n", "\n", "aDict = {}\n", "bDict = {'a':1, 'b':2, 'c':3}\n", "aDict\n", "bDict" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 更新某个元素" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2598" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "{'ann': 6585, 'bob': 8982, 'joe': 5802, 'zoe': 1225}" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "5802" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.core.interactiveshell import InteractiveShell\n", "InteractiveShell.ast_node_interactivity = \"all\"\n", "\n", "phonebook1 = {'ann':6575, 'bob':8982, 'joe':2598, 'zoe':1225, 'ann':6585}\n", "\n", "phonebook1['joe']\n", "phonebook1['joe'] = 5802\n", "phonebook1\n", "phonebook1['joe']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 添加元素" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'ann': 6585,\n", " 'bob': 8982,\n", " 'joe': 2598,\n", " 'zoe': 1225,\n", " 'john': 9876,\n", " 'mike': 5603,\n", " 'stan': 6898,\n", " 'eric': 7898}" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.core.interactiveshell import InteractiveShell\n", "InteractiveShell.ast_node_interactivity = \"all\"\n", "\n", "phonebook1 = {'ann':6575, 'bob':8982, 'joe':2598, 'zoe':1225, 'ann':6585}\n", "phonebook2 = {'john':9876, 'mike':5603, 'stan':6898, 'eric':7898}\n", "\n", "phonebook1.update(phonebook2)\n", "phonebook1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 删除某个元素" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'bob': 8982, 'joe': 2598, 'zoe': 1225}" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.core.interactiveshell import InteractiveShell\n", "InteractiveShell.ast_node_interactivity = \"all\"\n", "\n", "phonebook1 = {'ann':6575, 'bob':8982, 'joe':2598, 'zoe':1225, 'ann':6585}\n", "\n", "del phonebook1['ann']\n", "phonebook1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 逻辑操作符" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "dict_keys(['ann', 'bob', 'joe', 'zoe'])" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "False" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "dict_values([6585, 8982, 2598, 1225])" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "True" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "dict_items([('ann', 6585), ('bob', 8982), ('joe', 2598), ('zoe', 1225)])" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "False" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "phonebook1 = {'ann':6575, 'bob':8982, 'joe':2598, 'zoe':1225, 'ann':6585}\n", "\n", "'ann' in phonebook1\n", "\n", "phonebook1.keys()\n", "'stan' in phonebook1.keys()\n", "\n", "phonebook1.values()\n", "1225 in phonebook1.values()\n", "\n", "phonebook1.items()\n", "('stan', 6898) in phonebook1.items()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 可用来操作的内建函数" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "8" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "'zoe'" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "'ann'" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "['ann', 'bob', 'joe', 'zoe', 'john', 'mike', 'stan', 'eric']" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "('ann', 'bob', 'joe', 'zoe', 'john', 'mike', 'stan', 'eric')" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "{'ann', 'bob', 'eric', 'joe', 'john', 'mike', 'stan', 'zoe'}" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "['ann', 'bob', 'eric', 'joe', 'john', 'mike', 'stan', 'zoe']" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "['zoe', 'stan', 'mike', 'john', 'joe', 'eric', 'bob', 'ann']" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.core.interactiveshell import InteractiveShell\n", "InteractiveShell.ast_node_interactivity = \"all\"\n", "\n", "phonebook1 = {'ann':6575, 'bob':8982, 'joe':2598, 'zoe':1225, 'ann':6585}\n", "phonebook2 = {'john':9876, 'mike':5603, 'stan':6898, 'eric':7898}\n", "phonebook1.update(phonebook2)\n", "\n", "len(phonebook1)\n", "max(phonebook1)\n", "min(phonebook1)\n", "list(phonebook1)\n", "tuple(phonebook1)\n", "set(phonebook1)\n", "sorted(phonebook1)\n", "sorted(phonebook1, reverse=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 常用 Methods" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'john': 9876, 'mike': 5603, 'stan': 6898, 'eric': 7898}" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "{}" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "{'john': 9876, 'mike': 5603, 'stan': 6898, 'eric': 7898}" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "('zoe', 1225)" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "{'ann': 6585, 'bob': 8982, 'joe': 2598}" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "3538" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "{'ann': 6585, 'bob': 8982, 'joe': 2598}" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "3538" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "{'ann': 6585, 'bob': 8982, 'joe': 2598}" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "3538" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "{'ann': 6585, 'bob': 8982, 'joe': 2598, 'adam': 3538}" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.core.interactiveshell import InteractiveShell\n", "InteractiveShell.ast_node_interactivity = \"all\"\n", "\n", "phonebook1 = {'ann':6575, 'bob':8982, 'joe':2598, 'zoe':1225, 'ann':6585}\n", "phonebook2 = {'john':9876, 'mike':5603, 'stan':6898, 'eric':7898}\n", "\n", "phonebook3 = phonebook2.copy()\n", "phonebook3\n", "\n", "phonebook3.clear()\n", "phonebook3\n", "\n", "phonebook2 # .copy() 的 “原件” 不会发生变化\n", "\n", "p = phonebook1.popitem()\n", "p\n", "phonebook1\n", "\n", "p = phonebook1.pop('adam', 3538)\n", "p\n", "phonebook1\n", "\n", "p = phonebook1.get('adam', 3538)\n", "p\n", "phonebook1\n", "\n", "p = phonebook1.setdefault('adam', 3538)\n", "p\n", "phonebook1" ] }, { "cell_type": "markdown", "metadata": { "toc-hr-collapsed": true }, "source": [ "## 迭代各种容器中的元素" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "我们总是有这样的需求:对容器中的元素逐一进行处理(运算)。这样的时候,我们就用 `for` 循环去迭代它们。\n", "\n", "对于迭代 `range()` 和 `list` 中的元素我们已经很习惯了:" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n" ] } ], "source": [ "for i in range(3):\n", " print(i)" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n", "3\n" ] } ], "source": [ "for i in [1, 2, 3]:\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 迭代的同时获取索引" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "有时,我们想同时得到有序容器中的元素及其索引,那么可以调用 `enumerate()` 函数来帮我们:" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 P\n", "1 y\n", "2 t\n", "3 h\n", "4 o\n", "5 n\n" ] } ], "source": [ "s = 'Python'\n", "for i, c in enumerate(s):\n", " print(i, c)\n", " " ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 0\n", "1 1\n", "2 2\n" ] } ], "source": [ "for i, v in enumerate(range(3)):\n", " print(i, v)" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 ann\n", "1 bob\n", "2 joe\n", "3 john\n", "4 mike\n" ] } ], "source": [ "L = ['ann', 'bob', 'joe', 'john', 'mike']\n", "for i, L in enumerate(L):\n", " print(i, L)" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 ann\n", "1 bob\n", "2 joe\n", "3 john\n", "4 mike\n" ] } ], "source": [ "t = ('ann', 'bob', 'joe', 'john', 'mike')\n", "for i, t in enumerate(t):\n", " print(i, t)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 迭代前排序" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "可以用 `sorted()` 和 `reversed()` 在迭代前先排好序:" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 ann\n", "1 bob\n", "2 joe\n", "3 john\n", "4 mike\n" ] } ], "source": [ "t = ('bob', 'ann', 'john', 'mike', 'joe')\n", "for i, t in enumerate(sorted(t)):\n", " print(i, t)" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 mike\n", "1 john\n", "2 joe\n", "3 bob\n", "4 ann\n" ] } ], "source": [ "t = ('bob', 'ann', 'john', 'mike', 'joe')\n", "for i, t in enumerate(sorted(t, reverse=True)):\n", " print(i, t)" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 joe\n", "1 mike\n", "2 john\n", "3 ann\n", "4 bob\n" ] } ], "source": [ "t = ('bob', 'ann', 'john', 'mike', 'joe')\n", "for i, t in enumerate(reversed(t)):\n", " print(i, t)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 同时迭代多个容器" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "可以在 `zip()` 这个函数的帮助下,同时迭代两个或者两个以上的容器中的元素(这样做的前提是,多个容器中的元素数量最好相同):" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Let's assume a represents 1.\n", "Let's assume b represents 2.\n", "Let's assume c represents 3.\n", "Let's assume d represents 4.\n", "Let's assume e represents 5.\n", "Let's assume f represents 6.\n", "Let's assume g represents 7.\n", "Let's assume h represents 8.\n", "Let's assume i represents 9.\n", "Let's assume j represents 10.\n", "Let's assume k represents 11.\n", "Let's assume l represents 12.\n", "Let's assume m represents 13.\n", "Let's assume n represents 14.\n", "Let's assume o represents 15.\n", "Let's assume p represents 16.\n", "Let's assume q represents 17.\n", "Let's assume r represents 18.\n", "Let's assume s represents 19.\n", "Let's assume t represents 20.\n", "Let's assume u represents 21.\n", "Let's assume v represents 22.\n", "Let's assume w represents 23.\n", "Let's assume x represents 24.\n", "Let's assume y represents 25.\n", "Let's assume z represents 26.\n" ] } ], "source": [ "chars = 'abcdefghijklmnopqrstuvwxyz'\n", "nums = range(1, 27)\n", "for c, n in zip(chars, nums):\n", " print(f\"Let's assume {c} represents {n}.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 迭代字典中的元素" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ann 6585\n", "bob 8982\n", "joe 2598\n", "zoe 1225\n" ] } ], "source": [ "phonebook1 = {'ann':6575, 'bob':8982, 'joe':2598, 'zoe':1225, 'ann':6585}\n", "\n", "for key in phonebook1:\n", " print(key, phonebook1[key])" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ann 6585\n", "bob 8982\n", "joe 2598\n", "zoe 1225\n" ] } ], "source": [ "phonebook1 = {'ann':6575, 'bob':8982, 'joe':2598, 'zoe':1225, 'ann':6585}\n", "\n", "for key, value in phonebook1.items():\n", " print(key, value)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 总结" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "这一章的内容,只不过是 “多” 而已,一旦逻辑关系理顺,就会觉得很简单。而这一章的开头,已经是最好的总结了。\n", "\n", "最后需要补充的,只是两个参考链接,以后有什么搞不明白的地方,去那里翻翻就能找到答案:\n", "\n", "> * https://docs.python.org/3/tutorial/datastructures.html#dictionaries\n", "> * https://docs.python.org/3/library/stdtypes.html#typesmapping" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next Page" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.3" }, "toc-autonumbering": true }, "nbformat": 4, "nbformat_minor": 2 }