{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 字典 " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "字典 `dictionary` ,在一些编程语言中也称为 `hash` , `map` ,是一种由键值对组成的数据结构。\n", "\n", "顾名思义,我们把键想象成字典中的单词,值想象成词对应的定义,那么——\n", "\n", "一个词可以对应一个或者多个定义,但是这些定义只能通过这个词来进行查询。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 基本操作" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 空字典" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Python** 使用 `{}` 或者 `dict()` 来创建一个空的字典:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "dict" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = {}\n", "type(a)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "dict" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = dict()\n", "type(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "有了dict之后,可以用索引键值的方法向其中添加元素,也可以通过索引来查看元素的值:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 插入键值" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{'one': 'this is number 1', 'two': 'this is number 2'}" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a[\"one\"] = \"this is number 1\"\n", "a[\"two\"] = \"this is number 2\"\n", "a" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 查看键值" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'this is number 1'" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a['one']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 更新键值" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{'one': 'this is number 1, too', 'two': 'this is number 2'}" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a[\"one\"] = \"this is number 1, too\"\n", "a" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 初始化字典" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "可以看到,Python使用`key: value`这样的结构来表示字典中的元素结构,事实上,可以直接使用这样的结构来初始化一个字典:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'this is number 1'" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "b = {'one': 'this is number 1', 'two': 'this is number 2'}\n", "b['one']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 字典没有顺序" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "当我们 `print` 一个字典时,**Python**并不一定按照插入键值的先后顺序进行显示,因为字典中的键本身不一定是有序的。" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'two': 'this is number 2', 'one': 'this is number 1, too'}\n" ] } ], "source": [ "print a" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'two': 'this is number 2', 'one': 'this is number 1'}\n" ] } ], "source": [ "print b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "因此,**Python**中不能用支持用数字索引按顺序查看字典中的值,而且数字本身也有可能成为键值,这样会引起混淆:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "ename": "KeyError", "evalue": "0", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mKeyError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;31m# 会报错\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[0ma\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;31mKeyError\u001b[0m: 0" ] } ], "source": [ "# 会报错\n", "a[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 键必须是不可变的类型" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "出于hash的目的,Python中要求这些键值对的**键**必须是**不可变**的,而值可以是任意的Python对象。\n", "\n", "一个表示近义词的字典:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{'immutable': ['fixed',\n", " 'set',\n", " 'rigid',\n", " 'inflexible',\n", " 'permanent',\n", " 'established',\n", " 'carved in stone'],\n", " 'mutable': ['changeable',\n", " 'variable',\n", " 'varying',\n", " 'fluctuating',\n", " 'shifting',\n", " 'inconsistent',\n", " 'unpredictable',\n", " 'inconstant',\n", " 'fickle',\n", " 'uneven',\n", " 'unstable',\n", " 'protean']}" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "synonyms = {}\n", "synonyms['mutable'] = ['changeable', 'variable', 'varying', 'fluctuating',\n", " 'shifting', 'inconsistent', 'unpredictable', 'inconstant',\n", " 'fickle', 'uneven', 'unstable', 'protean']\n", "synonyms['immutable'] = ['fixed', 'set', 'rigid', 'inflexible', \n", " 'permanent', 'established', 'carved in stone']\n", "synonyms" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "另一个例子:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{500: {'mag': 0.05, 'width': 20},\n", " 760: {'mag': 0.04, 'width': 25},\n", " 3001: {'mag': 0.05, 'width': 80},\n", " 4180: {'mag': 0.03, 'width': 30}}" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 定义四个字典\n", "e1 = {'mag': 0.05, 'width': 20}\n", "e2 = {'mag': 0.04, 'width': 25}\n", "e3 = {'mag': 0.05, 'width': 80}\n", "e4 = {'mag': 0.03, 'width': 30}\n", "# 以字典作为值传入新的字典\n", "events = {500: e1, 760: e2, 3001: e3, 4180: e4}\n", "events" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "键(或者值)的数据类型可以不同:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[{'first': 'Sam', 'last': 'Malone', 'name': 35},\n", " {'first': 'Woody', 'last': 'Boyd', 'name': 21},\n", " {'first': 'Norm', 'last': 'Peterson', 'name': 34},\n", " {'first': 'Diane', 'last': 'Chambers', 'name': 33}]" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "people = [\n", " {'first': 'Sam', 'last': 'Malone', 'name': 35},\n", " {'first': 'Woody', 'last': 'Boyd', 'name': 21},\n", " {'first': 'Norm', 'last': 'Peterson', 'name': 34},\n", " {'first': 'Diane', 'last': 'Chambers', 'name': 33}\n", "]\n", "people" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 使用 dict 初始化字典" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "除了通常的定义方式,还可以通过 `dict()` 转化来生成字典:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{'foozelator': 123, 'frombicator': 18, 'snitzelhogen': 23, 'spatzleblock': 34}" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "inventory = dict(\n", " [('foozelator', 123),\n", " ('frombicator', 18), \n", " ('spatzleblock', 34), \n", " ('snitzelhogen', 23)\n", " ])\n", "inventory" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "利用索引直接更新键值对:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{'foozelator': 123, 'frombicator': 19, 'snitzelhogen': 23, 'spatzleblock': 34}" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "inventory['frombicator'] += 1\n", "inventory" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 适合做键的类型" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "在不可变类型中,整数和字符串是字典中最常用的类型;而浮点数通常不推荐用来做键,原因如下:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false }, "outputs": [ { "ename": "KeyError", "evalue": "3.3", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mKeyError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[0mdata\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m1.1\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;36m2.2\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m6.6\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 3\u001b[0m \u001b[1;31m# 会报错\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 4\u001b[1;33m \u001b[0mdata\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m3.3\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;31mKeyError\u001b[0m: 3.3" ] } ], "source": [ "data = {}\n", "data[1.1 + 2.2] = 6.6\n", "# 会报错\n", "data[3.3]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "事实上,观察`data`的值就会发现,这个错误是由浮点数的精度问题所引起的:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{3.3000000000000003: 6.6}" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "有时候,也可以使用元组作为键值,例如,可以用元组做键来表示从第一个城市飞往第二个城市航班数的多少:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": true }, "outputs": [], "source": [ "connections = {}\n", "connections[('New York', 'Seattle')] = 100\n", "connections[('Austin', 'New York')] = 200\n", "connections[('New York', 'Austin')] = 400" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "元组是有序的,因此 `('New York', 'Austin')` 和 `('Austin', 'New York')` 是两个不同的键:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "200\n", "400\n" ] } ], "source": [ "print connections[('Austin', 'New York')]\n", "print connections[('New York', 'Austin')]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 字典方法" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `get` 方法" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "之前已经见过,用索引可以找到一个键对应的值,但是当字典中没有这个键的时候,Python会报错,这时候可以使用字典的 `get` 方法来处理这种情况,其用法如下:\n", "\n", " `d.get(key, default = None)`\n", "\n", "返回字典中键 `key` 对应的值,如果没有这个键,返回 `default` 指定的值(默认是 `None` )。" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "collapsed": true }, "outputs": [], "source": [ "a = {}\n", "a[\"one\"] = \"this is number 1\"\n", "a[\"two\"] = \"this is number 2\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "索引不存在的键值会报错:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false }, "outputs": [ { "ename": "KeyError", "evalue": "'three'", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mKeyError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0ma\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m\"three\"\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;31mKeyError\u001b[0m: 'three'" ] } ], "source": [ "a[\"three\"]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "改用get方法:" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "None\n" ] } ], "source": [ "print a.get(\"three\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "指定默认值参数:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'undefined'" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a.get(\"three\", \"undefined\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `pop` 方法删除元素" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`pop` 方法可以用来弹出字典中某个键对应的值,同时也可以指定默认参数:\n", "\n", " `d.pop(key, default = None)`\n", "\n", "删除并返回字典中键 `key` 对应的值,如果没有这个键,返回 `default` 指定的值(默认是 `None` )。" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{'one': 'this is number 1', 'two': 'this is number 2'}" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "弹出并返回值:" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": false, "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "'this is number 2'" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a.pop(\"two\")" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{'one': 'this is number 1'}" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "弹出不存在的键值:" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'not exist'" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a.pop(\"two\", 'not exist')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "与列表一样,`del` 函数可以用来删除字典中特定的键值对,例如:" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{}" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "del a[\"one\"]\n", "a" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `update`方法更新字典" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "之前已经知道,可以通过索引来插入、修改单个键值对,但是如果想对多个键值对进行操作,这种方法就显得比较麻烦,好在有 `update` 方法:\n", "\n", " `d.update(newd)`\n", "\n", "将字典`newd`中的内容更新到`d`中去。" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'born': 1831, 'last': 'Maxwell', 'first': 'Jmes'}\n" ] } ], "source": [ "person = {}\n", "person['first'] = \"Jmes\"\n", "person['last'] = \"Maxwell\"\n", "person['born'] = 1831\n", "print person" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "把'first'改成'James',同时插入'middle'的值'Clerk':" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'middle': 'Clerk', 'born': 1831, 'last': 'Maxwell', 'first': 'James'}\n" ] } ], "source": [ "person_modifications = {'first': 'James', 'middle': 'Clerk'}\n", "person.update(person_modifications)\n", "print person" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `in`查询字典中是否有该键" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "collapsed": true }, "outputs": [], "source": [ "barn = {'cows': 1, 'dogs': 5, 'cats': 3}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`in` 可以用来判断字典中是否有某个特定的键:" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "'chickens' in barn" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "'cows' in barn" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `keys` 方法,`values` 方法和`items` 方法" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " `d.keys()` \n", "\n", "返回一个由所有键组成的列表;\n", "\n", " `d.values()` \n", "\n", "返回一个由所有值组成的列表;\n", "\n", " `d.items()` \n", "\n", "返回一个由所有键值对元组组成的列表;" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "['cows', 'cats', 'dogs']" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "barn.keys()" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[1, 3, 5]" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "barn.values()" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[('cows', 1), ('cats', 3), ('dogs', 5)]" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "barn.items()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.11" } }, "nbformat": 4, "nbformat_minor": 0 }