信息管理专业Python教程

Similar documents
Python a p p l e b e a r c Fruit Animal a p p l e b e a r c 2-2

数据结构与算法 - Python基础

C/C++ - 字符输入输出和字符确认

電腦做什麼事~第七章

C/C++程序设计 - 字符串与格式化输入/输出

C/C++语言 - C/C++数据

Spyder Anaconda Spyder Python Spyder Python Spyder Spyder Spyder 開始 \ 所有程式 \ Anaconda3 (64-bit) \ Spyder Spyder IPython Python IPython Sp

新・明解Python入門

C/C++ - 文件IO

LOVE IS OVER LOVE LOVE LOVE LOVE IS EVERYTHING LOVE LOVE LOVE LOVER'S QUEEN LYDIA MAYBE TOMORROW MEN'S TALK MY DEAR MY FRIEND MY OH MY MY SUMMER DREAM

Learn_Perl 3-02.pdf

C/C++ - 字符串与字符串函数

星河33期.FIT)

WWW PHP

Microsoft Word - ACG chapter00c-3ed.docx

Lorem ipsum dolor sit amet, consectetuer adipiscing elit

C/C++语言 - 运算符、表达式和语句

99 學年度班群總介紹 第 370 期 班群總導 陳怡靜 G45 班群總導 陳怡靜(河馬) A 家 惠如 家浩 T 格 宜蓁 小 霖 怡 家 M 璇 均 蓁 雴 家 數學領域 珈玲 國燈 英領域 Kent

2-7.FIT)

新・解きながら学ぶJava

软件测试(TA07)第一学期考试

Microsoft Word - 第3章.doc

C/C++ - 函数

豐 邑 家 族 季 刊 編 者 的 話 No.07 彼 此 相 愛 總 編 輯 : 邱 崇 喆 主 編 : 戴 秋 柑 編 輯 委 員 : 黃 淑 美 盧 永 吉 王 森 生 趙 家 明 林 孟 姿 曾 淑 慧 執 行 編 輯 : 豐 邑 建 設 企 劃 課 出 版 發 行 :

CC213

C C

TX-NR3030_BAS_Cs_ indd

Microsoft Word 電腦軟體設計.doc

高中英文科教師甄試心得

<4D F736F F D D342DA57CA7DEA447B14D2DA475B57BBB50BADEB27AC3FEB14DA447B8D5C344>

C

39 屆 畢 業 典 禮

untitled

Microsoft Word 軟體設計第二部份範例試題_C++_ _1_.doc

Untitiled

100學年度大學推甄申請面試題庫

四川省普通高等学校

<4D F736F F F696E74202D20312EB9FEB6FBB1F5B9A4D2B5B4F3D1A7D5E7C1BCA3BAC3E6CFF2D1D0BEBFC9FAB8B4CAD4B5C4BDE1B9B9BBAFC3E6CAD4BFBCBACBCCBDCBF7D3EBCAB5BCF92E BBCE6C8DDC4A3CABD5D>

參 加 第 二 次 pesta 的 我, 在 是 次 交 流 營 上 除 了, 與 兩 年 沒 有 見 面 的 朋 友 再 次 相 聚, 加 深 友 誼 外, 更 獲 得 與 上 屆 不 同 的 體 驗 和 經 歴 比 較 起 香 港 和 馬 來 西 亞 的 活 動 模 式, 確 是 有 不 同 特

前 言 香 港 中 文 大 學 優 質 學 校 改 進 計 劃 ( 下 稱 計 劃 ) 團 隊 自 1998 年 起 積 極 於 本 地 推 動 理 論 及 實 踐 並 重 的 學 校 改 進 工 作, 並 逐 步 發 展 成 為 本 地 最 具 規 模 的 校 本 支 援 服 務 品 牌, 曾 支

Lorem ipsum dolor sit amet, consectetuer adipiscing elit

课程12-7.FIT)

目 錄 壹 青 輔 會 結 案 附 件 貳 活 動 計 劃 書 參 執 行 內 容 一 教 學 內 容 二 與 當 地 教 師 教 學 交 流 三 服 務 執 行 進 度 肆 執 行 成 效 一 教 學 課 程 二 與 當 地 教 師 教 學 交 流 三 服 務 滿 意 度 調 查 伍 服 務 檢

CC213

C/C++ 语言 - 循环

3.1 num = 3 ch = 'C' 2

Love Actually 真 的 戀 愛 了!? 焦 點 主 題 2035 年 一 個 寒 冷 卻 又 放 晴 的 下 午, 爸 媽 一 大 清 早 已 上 班, 只 得 小 奈 獨 個 兒 待 在 家 中, 奢 侈 地 享 受 著 她 的 春 節 假 期 剛 度 過 了 期 考 的 艱 苦 歲

Microsoft Word - 新加坡手冊封面.docx

硕 士 学 位 论 文 论 文 题 目 : 北 岛 诗 歌 创 作 的 双 重 困 境 专 业 名 称 : 中 国 现 当 代 文 学 研 究 方 向 : 中 国 新 诗 研 究 论 文 作 者 : 奚 荣 荣 指 导 老 师 : 姜 玉 琴 2014 年 12 月

附件1.FIT)

毛主席的猪

Microsoft Word - HERBRECIPES《中國藥膳》.doc

循经指压疗法



CC213

C/C++语言 - 分支结构

Microsoft PowerPoint - Lecture7II.ppt

四川汉墓中所反映的南传早期佛像艺术/范小平

Fun Time (1) What happens in memory? 1 i n t i ; 2 s h o r t j ; 3 double k ; 4 char c = a ; 5 i = 3; j = 2; 6 k = i j ; H.-T. Lin (NTU CSIE) Referenc

全 国 高 等 职 业 教 育 规 划 教 材 21 世 纪 高 职 高 专 规 划 教 材 系 列 高 等 职 业 教 育 计 算 机 专 业 规 划 教 材 选 题 征 集 通 知 一 选 题 范 围 ( 不 仅 限 于 此 ) 选 题 方 向 选 题 名 计 算 机 基 础 计 算 机 应 用

Microsoft Word - 01.DOC

Microsoft Word - 第四組心得.doc

Chapter 9: Objects and Classes

Q&A 前 言 (2008


PowerPoint 演示文稿

Microsoft Word

coverage2.ppt

Microsoft Word - 长安大学.doc

<4D F736F F D20312EA1B6BDCCCAA6D7CAB8F1CCF5C0FDA1B72E646F63>

LEETCODE leetcode.com 一 个 在 线 编 程 网 站, 收 集 了 IT 公 司 的 面 试 题, 包 括 算 法, 数 据 库 和 shell 算 法 题 支 持 多 种 语 言, 包 括 C, C++, Java, Python 等 2015 年 3 月 份 加 入 了 R

科学计算的语言-FORTRAN95

untitled

Untitled-2.indd

( 一 ) 實 習 的 時 候 就 和 讀 書 會 的 同 學 一 起 把 陳 嘉 陽 紮 實 地 讀 過 一 遍 了, 也 因 此 在 考 完 教 檢 之 後, 我 們 只 有 把 不 熟 或 是 常 考 的 章 節 再 導 讀 一 次 ( 例 如 : 統 計 行 政 法 規 ), 主 力 則 是

三維空間之機械手臂虛擬實境模擬

Microsoft Word - TIP006SCH Uni-edit Writing Tip - Presentperfecttenseandpasttenseinyourintroduction readytopublish

目錄

級 任 介 紹 班 主 任 其 他 級 任 2A 羅 彩 岫 主 任 吳 毅 蕙 老 師 2B 徐 玲 老 師 陳 詠 詩 老 師 2C 梁 麗 興 老 師 尹 南 老 師 2D 曾 康 老 師 李 樂 雯 老 師 2E 黃 蕙 明 老 師

FY.DOC

北 京 奧 運 會 上 倒 舉 中 共 國 旗 的 小 男 孩

編 者 的 話 文 字 / KK 人 天 生 便 具 有 好 奇 心, 想 對 週 遭 事 物 更 加 瞭 解, 以 滿 足 自 己 的 求 知 渴 望 孩 子 可 以 透 過 父 母 的 敘 說 表 演, 激 發 想 像 創 造 邏 輯 推 理 判 斷 等 能 力 父 母 最 能 夠 了 解 子

Microsoft PowerPoint - OPVB1基本VB.ppt

ebook65-20

101_


國 立 政 治 大 學 教 育 學 系 2016 新 生 入 學 手 冊 目 錄 表 11 國 立 政 治 大 學 教 育 學 系 博 士 班 資 格 考 試 抵 免 申 請 表 論 文 題 目 申 報 暨 指 導 教 授 表 12 國 立 政 治 大 學 碩 博 士 班 論

Transcription:

目 錄 1. 介 i. 者 序 ii. 作 者 序 2. 什 么 要 学 程 3. 量 表 式 与 句 4. 条 件 行 5. 函 数 6. 迭 代 7. 字 符 串 8. 文 件 9. 列 表 10. 字 典 11. 元 12. 正 表 式 13. 网 程 14. Web Services 15. 数 据 与 化 言 SQL 16. 数 据 可 化 17. 常 任 自 化 理 18. 附 A 19. 附 B 20. 附 C 2

介 Python for Informatics( 中 文 版 ) 信 息 管 理 Python 教 程 程 初 学 者, 介 如 何 程, 使 用 Python 行 数 据 理 与 数 据 可 化 本 旨 在 透 数 据 探 索 的, 向 学 生 介 程 与 算 思 Python 可 比 子 表 格 强 大 的 解 决 工 具 Python 是 一 种 易 于 使 用 与 学 的 程 言, 在 Windows Mac 与 Linux 算 机 上 都 可 以 免 取 本 采 用 署 名 - 非 商 性 使 用 - 相 同 方 式 共 享 可 形 式, 提 供 各 种 子 格 式 的 免 下 外, 本 配 套 一 免 在 自 学 程 (http://www.pythonlearn.com) 中 所 有 内 容 材 料 是 开 放 的, 可 用 于 改 翻 明 得 益 于 开 源 与 共 享 精 神, 根 据 知 共 享 CC-BY-SA, 由 作 者 授, 本 的 体 中 文 版 翻 与 开 放 出 版 得 以 利 完 成 翻 工 作 由 范, 得 到 四 川 大 学 公 共 管 理 学 院 信 息 管 理 合 室 的 大 力 支 持, 胡 康 林 校 了 本 并 提 出 宝 意, 信 息 管 理 与 信 息 系 位 本 科 生 参 与 了 部 分 章 的 翻 与 校 功 翻 第 1 3 6 8 9 10 章 及 附 王 翻 第 2 4 5 7 章 范 翻 第 11-16 章, 稿 与 定 稿 由 于 精 力 与 水 平 有 限, 中 翻 在 所 免 迎 各 位 者 批 指 正, 我 会 汲 取 建, 及 行 修 勘 献 感 志 暹 正 了 文 中 的 一 些 和 提 出 Gitbook Markdown 法 解 析 介 3

者 序 翻 普 遍 被 出 力 不 好, 次 我 把 翻 当 成 一 件 情 的 活 来 干 了 本 序 由 4 个 和 1 个 明 成, 希 望 能 引 起 相 关 者 的 共 什 么 要 冠 以 信 息 管 理 之 名? Informatics 在 中 文 境 下 是 个 神 秘 的, 有 情 学 信 息 学 等 法, 但 个 名 称 都 不 合 适 国 内 的 情 学 不 是 搞 的, 信 息 学 是 搞 通 的 在 信 息 的 世 界 里, 美 的 会 无 不 在 通 俗,Informatics 属 于 信 息 管 理 大 范 畴, 是 信 息 管 理 活 的 高 段, 通 数 据 分 析 与 掘, 提 供 管 理 与 决 策 有 价 的 信 息 ( 即 情 ) 信 息 管 理 听 起 来 非 常 有 魅 惑 力 从 早 期 一 波 波 的 数 字 化 浪 潮 到 当 代 的 大 数 据, 信 息 管 理 无 可 争 地 在 信 息 化 代 革 的 先, 一 直 与 各 型 数 据 ( 里 可 信 息 的 体 ) 打 交 道 个 的 主 是 数 据 ( 信 息 ) 的 建 采 集 加 工 与 分 析 利 用 等 什 么 信 息 管 理 要 学 程? 信 息 管 理 离 不 开 信 息 技, 倒 不 如 各 信 息 技 是 解 决 信 息 管 理 中 的 而 被 明 的 依 据 此 理, 学 程 是 用 技 方 法 与 工 具 来 解 决 信 息 管 理 中 的 具 体 和 提 高 工 作 效 率 看 似 有 道 理, 但 中 程 个 的 学 生 感 到 困 惑 和 畏 惧, 常 常 与 算 机 的 程 混 淆 重, 学 起 来 既 无 趣 又 痛 苦 什 么 是 Python? C 言 是 大 多 数 信 息 管 理 开 的 第 一 程 毋 庸 置 疑, 学 C 言 首 先 从 程 思 想 上 武 装 了 初 学 者 然 而, 信 息 管 理 的 学 生 未 来 并 不 打 算 从 事 程 言 本 身 的 研 究, 更 多 想 要 用 程 工 具 来 解 决 外, 信 息 管 理 程 体 系 里 并 没 有 多 的 程 深 入 程, 程 入 与 用 接 比 薄 弱 或 直 接 偏 向 了 信 息 系 开 ( 管 理 信 息 系 方 向 ), 学 生 从 C 言 向 其 他 眼 花 乱 的 高 程 言 感 到 困, 致 学 的 成 就 感 普 遍 不 高 学 了 程, 拿 着 一 全 国 算 机 等 考 C 言, 没 有 什 么 意, 用 不 起 来 是 最 大 的 所 在 Python 言 的 功 能 全 面 性 与 易 于 学 等 特 点 在 程 言 入 广 泛 流 行, 近 些 年 可 以 是 深 得 民 心 除 了 言 本 身 的 点 之 外,Python 言 非 常 适 合 信 息 管 理, 原 因 在 于 它 的 功 能 性 全 面 渗 透 到 信 息 管 理 的 各 个, 如 中 介 的 文 本 理 数 据 采 集 数 据 存 与 用 Web Services 等 主 由 Python 做 到 了 很 好 的 知 串 可 以,Python 提 供 了 程 学 与 技 用 通 的 一 化 平 台 本 将 Python 言 的 解 与 具 体 数 据 管 理 相 合, 在 一 定 程 度 做 到 了 学 会 即 用, 是 目 前 比 少 的 适 合 信 息 管 理 的 程 入 教 材 什 么 要 翻 本? 开 篇 也 提 到 是 有 情 的 事 儿 去, 我 曾 是 国 内 最 早 一 批 信 息 管 理 与 信 息 系 的 学 生, 在, 我 是 个 的 一 名 教 十 多 年 来 与 个 共 同 成, 自 身 也 了 程 的 种 种 迷 茫 与 困 惑 随 着 信 息 技 的 快 速 化, 教 学 内 容 与 手 段 的 与 俱 也 得 非 常 必 要 工 作 之 后, 我 看 到 了 Python 来 打 通 信 息 管 理 程 学 症 的 可 能 性, 开 始 翻 各 Python 籍 眼 前 的 本 人 眼 前 一 亮, 我 非 常 同 本 作 者 的 教 学 理 念, 他 的 努 力 信 息 管 理 学 生 能 松 愉 悦 地 学 一 功 能 强 大 的 用 型 高 程 言 通 翻 本, 希 望 更 多 信 息 管 理 的 学 生 能 找 到 程 入 的 匙, 将 Python 作 通 向 数 据 管 理 与 分 析 技 能 养 成 的 一 座 梁, 少 走 一 些 弯 路 我 而 言, 更 多 是 在 未 来 的 教 学 中 引 入 Python 内 容, 出 适 合 国 内 信 息 管 理 的 数 据 技 能 用 型 程 如 何 本? 者 序 4

然 本 不 需 要 什 么 技 基, 但 最 好 具 操 作 系 数 据 与 互 网 的 一 些 基 知 本 内 容 分 大 部 分 : 第 1-10 章 涵 盖 Python 言 的 基 知 ; 第 11-16 章 是 Python 在 数 据 管 理 与 分 析 中 的 用 中 的 所 有 示 例 与 代 均 可 免 下, 建 操 作, 手 并 用 收 才 会 更 多 12-15 章 的 程 序 代 相 复, 如 果 感 到 自 学 度 大, 可 先 按 照 中 解, 行 源 代, 出 果 看 效 果, 走 通 之 后 再 回 来 慢 慢 研 究 代 工 欲 善 其 事 必 先 利 其 器 正 如 本 的 副, 希 望 Python 能 成 你 学 道 路 上 探 索 信 息 世 界 的 一 把 利 器 致 首 先 要 感 美 国 密 西 根 大 学 信 息 学 院 Charles Severance 教 授 的 慷 慨 支 持, 使 得 本 得 以 利 自 由 出 版 技 翻 不 是 的 文 字 工 作, 心 力, 事 无 巨 也 以 做 到 不 出 从 目 到 完 成 近 3 个 月 感 段 以 来 目 提 供 支 持 和 关 心 我 的 所 有 人, 没 有 你 的 鼓 励 与 帮 助, 凭 我 个 人 无 法 完 成 工 作, 段 令 人 忘 感 一 路 有 你! 范 四 川 大 学 信 息 管 理 技 系 2015 年 6 月 于 雪 城 者 序 5

作 者 序 信 息 管 理 Python 教 程 : 一 本 混 的 开 源 在 学 界, 科 研 人 不 断 被 洗 的 是 表 或 消 亡, 从 开 始 造, 做 出 原 始 新 本 不 是 原 始 新, 而 是 像 算 机 科 学 家 一 思 考 Python ( 以 下 称 思 考 Python )(Allen B. Downey, Jeff Elkner 等 著 ) 本 的 一 次 混 2009 年 12 月, 我 在 密 西 根 大 学 准 授 SI502- 网 程 ( 第 五 学 期 开 ), 决 定 开 始 写 一 本 重 于 数 据 探 索, 而 不 是 理 解 算 法 与 抽 象 理 的 Python 教 材 我 的 SI502 程 目 是 培 养 学 生 使 用 Python 的 生 数 据 理 技 能 我 的 学 生 中 很 少 有 人 打 算 成 算 机 程 序 相 反, 他 的 划 是 理 律 生 物 学 家 学 家 等 他 希 望 在 所 从 事 的 行 中 能 熟 用 技 我 似 乎 找 不 到 适 合 的 Python 教 材, 重 以 数 据 中 心 的, 因 此 我 决 定 要 写 一 本 我 打 算 利 用 假 期 从 写 本, 所 幸, 在 放 假 前 三 周 的 教 工 会 上,Atul Prakash 博 士 我 一 本 思 考 Python, 他 在 那 个 学 期 使 用 本 授 Python 程 是 一 本 很 棒 的 算 机 教 材, 特 点 在 于 篇 幅 短 直 白 的 解 以 及 易 于 学 本 的 整 体 已 整 尽 可 能 快 速 地 解 决 数 据 分 析, 包 括 一 系 列 从 基 到 高 的 可 行 的 数 据 分 析 示 例 与 第 2-10 章 与 思 考 Python 内 容 似, 主 要 区 如 下 : 面 向 数 的 示 例 与 被 面 向 数 据 的 取 代 ; 主 的 序 按 照 循 序 原, 从 数 据 理 到 复 的 数 据 分 析 解 决 方 案 ; 一 些 主, 例 如 try 与 except 整 到 前 面, 作 第 3 章 条 件 的 部 分 内 容 由 于 函 数 比 抽 象, 没 有 早 出, 当 需 要 理 程 序 的 复 性 才 予 以 介 几 乎 所 有 用 定 的 函 数 都 从 第 4 章 的 例 代 与 中 移 除 了 本 不 会 出 1 个 第 1 章 和 第 11-16 章 的 内 容 都 是 全 新 的, 主 要 介 Python 的 用, 包 括 一 些 用 于 数 据 分 析 的 Python 示 例, 例 如, 搜 索 与 解 析 的 正 表 式, 算 机 上 任 的 自 化 行, 通 网 索 数 据, 采 集 网 数 据,Web Services 的 使 用, 解 析 XML 与 JSON 数 据, 使 用 化 言 SQL 行 数 据 的 建 与 使 用 等 本 做 出 些 整 的 最 目 是, 从 算 机 角 向 信 息 管 理 角, 涵 盖 技 入 程 必 需 的 主, 即 使 的 学 生 并 不 打 算 成 的 程 序 也 会 感 到 有 用 本 感 趣 的 学 生 想 要 一 步 探 索 的, Alle B. Downey 的 思 考 Python 由 于 本 的 内 容 存 在 多 重, 学 生 能 从 那 本 中 快 速 掌 握 更 多 技 程 技 能 与 提 升 算 法 思 考 能 力 外, 本 的 写 作 格 相 似, 完 本 之 后 能 很 容 易 通 思 考 Python 思 考 Python 本 的 版 所 有 者 Allen 授 我 中 内 容 的 版 做 了 修 改, 将 本 中 保 留 的 他 中 的 内 容 可 从 GNU 自 由 文 档 可 更 最 近 流 行 的 知 共 享 以 相 同 方 式 共 享 (CC-BY-SA) 一 做 法 符 合 开 放 文 档 可 从 GFDJ 到 CC- BY-SA 的 ( 如, 基 百 科 的 授 方 式 ) CC-BY-SA 可 保 留 了 最 著 的 版, 同 又 允 新 作 者 直 接 重 用 中 他 得 合 适 的 内 容 我 得 本 是 教 学 料 开 放 的 一 个 典 范, 未 来 的 教 育 而 言 非 常 重 要 感 Alleb B. Downey 和 大 学 出 版 社 做 出 的 前 瞻 决 定, 本 可 以 在 开 放 版 下 出 版 希 望 他 我 努 力 的 果 感 到 欣 慰, 我 也 希 望 者 我 的 集 体 努 力 感 到 高 我 要 感 Allen B. Downey 与 Lauren Cowles 在 解 决 本 版 提 供 的 帮 助 耐 心 与 指 Charles Severance www.dr-chuck.com Ann Arbor, MI, USA 2013 年 9 月 9 号 Charles Severance 博 士 是 密 西 根 大 学 信 息 学 院 的 床 副 教 授 1. 当 然, 里 出 的 除 外 作 者 序 6

作 者 序 7

第 1 章 什 么 要 学 程 程 是 一 极 具 造 性 和 有 益 的 活 程 的 原 因 很 多, 大 到 生 去 解 决 一 个 困 的 数 据 分 析, 小 到 因 帮 助 人 解 决 一 个 而 得 快 本 假 定 每 个 人 都 需 要 知 道 怎 程, 一 旦 学 会 程, 你 就 会 想 要 用 个 新 技 能 做 些 什 么 了 我 的 日 常 生 活 中 算 机 无 不 在, 大 到 本, 小 到 手 机 些 算 机 可 帮 助 我 打 理 很 多 事 情 的 私 人 助 理 如 今 的 算 机 硬 件 从 根 本 上 是 建 在 不 断 回 答 我 提 的 基 上, 即 下 一 步 想 要 做 什 么? 程 序 在 硬 件 之 上 添 加 了 操 作 系 和 用 程 序, 我 手 中 拿 到 的 成 品 是 一 个 很 有 用 的 个 人 数 字 助 理 (PDA,Personal Digital Assistant), 它 能 帮 我 理 很 多 不 同 的 事 情 算 机 行 速 度 很 快 并 有 大 量 的 内 存, 如 果 我 知 道 了 如 何 与 算 机 通, 告 算 机 想 要 它 接 下 来 做 什 么, 更 好 地 使 用 算 机 很 有 帮 助 如 果 掌 握 了 算 机 通 言, 就 能 算 机 根 据 我 的 意 愿 完 成 一 些 重 复 性 工 作 有 趣 的 是, 算 机 能 任 并 且 做 得 很 好 的 工 作 就 是 那 些 常 我 人 感 到 无 聊 令 人 麻 木 的 事 情 例 如, 本 章 的 前 三 段, 找 出 出 率 最 高 的 是 一 个, 以 及 个 共 出 了 多 少 次 尽 管 你 能 在 短 内 和 理 解 些 文 字, 但 要 它 行 就 很 痛 苦 了 不 是 人 的 大 擅 解 决 的 算 机 恰 好 相 反, 很 像 人 一 和 理 解 一 段 文 字, 但 是 行 文 字 并 告 你 出 率 最 高 的 及 其 出 次 数, 算 机 而 言 却 是 非 常 容 易 的 : python words.py Enter file:words.txt to 16 个 人 信 息 分 析 助 理 很 快 告 我, to 在 本 章 前 三 段 中 一 共 出 了 16 次 事 上, 算 机 擅 做 人 不 擅 做 的 事, 就 是 什 么 你 需 要 熟 掌 握 一 与 算 机 的 言 一 旦 学 会 新 言, 你 就 可 以 将 枯 燥 的 工 作 指 派 你 的 算 机 搭 档 了, 留 出 更 多 的 去 做 适 合 你 自 己 的 事 在 种 合 作 关 系 中, 你 的 献 是 才 思 直 力 和 造 力 1.1 新 与 机 本 不 是 程 序 准 的, 程 是 份 非 常 有 前 途 的 工 作, 可 算 是 物 与 精 神 双 丰 收 他 人 造 有 用 的 的 与 智 能 的 程 序 是 一 新 性 很 强 的 活 你 的 算 机 或 PDA 通 常 安 装 了 来 自 多 不 同 程 序 开 的 各 种 件, 每 一 款 件 都 想 要 吸 引 你 的 注 意 力 和 趣 它 尽 其 所 能 来 足 你 的 需 求, 在 使 用 程 中 你 得 的 用 体 在 某 些 情 况 下, 当 你 了 一 个 件, 个 件 的 开 者 就 会 因 你 的 而 直 接 得 收 益 如 果 将 程 序 看 作 是 程 序 的 新 性 出, 那 么 下 就 是 一 个 更 形 象 的 PDA 模 型 : 什 么 要 学 程 8

本 的 写 作 初 衷 不 是 了 或 者 取 悦 最 用, 而 是 我 能 更 好 地 理 生 活 中 的 数 据 与 信 息 开 始 学 程, 你 既 是 程 序, 也 是 你 所 写 程 序 的 最 用 当 你 得 了 程 序 的 技 能, 如 果 程 你 感 到 有 新 活 力 的, 到 你 的 想 法 也 会 生 改, 向 他 人 开 程 序 也 不 定 1.2 算 机 硬 件 架 学 种 向 算 机 指 令 来 开 件 的 言 之 前, 我 需 要 了 解 一 下 算 机 的 成 如 果 拆 开 你 的 算 机 或 者 手 机, 仔 察 就 会 以 下 些 件 : 些 件 的 一 般 定 如 下 : 中 央 理 器 (Central Processing Unit,CPU) 是 解 决 下 一 步 做 什 么 而 存 在 的 件 如 果 算 机 理 速 度 到 3.0 GHz, 就 意 味 着 CPU 每 秒 会 提 30 次 下 一 步 做 什 么? 你 不 得 不 学 会 如 何 跟 CPU 如 此 快 速 地 交 与 保 持 同 步 主 存 器 (Main Memory) 用 来 存 CPU 即 刻 需 要 的 信 息 主 存 器 的 速 度 几 乎 与 CPU 不 相 上 下 但 是, 关 算 机 之 后 主 存 器 里 的 信 息 也 就 消 失 了 助 存 器 (Secondary Memory) 也 是 用 来 存 信 息 的, 但 是 它 比 主 存 器 速 度 慢 很 多 助 存 器 的 点 是, 它 可 以 在 算 机 不 情 况 下 存 信 息 常 助 存 器 包 括 磁 和 存 存 通 常 用 在 U 和 便 携 式 音 播 放 器 上 入 出 (Input and Output Devices) 包 括 屏 幕 鼠 麦 克 声 器 以 及 触 摸 板 等 些 都 是 用 来 与 算 机 行 交 互 的 如 今 大 多 数 算 机 之 建 立 了 网 接, 通 网 取 信 息 我 可 以 将 网 看 成 信 息 存 与 索 速 度 很 慢 的 一 个 空, 而 且 不 是 那 么 定 从 某 种 意 上, 网 是 速 度 很 慢 且 并 不 是 那 么 可 靠 的 助 存 器 些 件 的 工 作 原 理 最 好 是 交 算 机 厂 商 吧 里 只 是 了 掌 握 一 些, 在 程 方 便 提 及 些 件 作 一 名 程 序, 你 的 工 作 就 是 利 用 并 些 源 来 解 决 和 分 析 数 据 作 程 序, 你 主 要 与 CPU 打 交 道, 告 它 下 一 步 做 什 么 有, 你 要 告 CPU 用 主 存 器 助 存 器 网 或 入 出 什 么 要 学 程 9

你 需 要 成 回 答 CPU 下 一 步 做 什 么 的 人 但 把 你 到 5 毫 米 高, 塞 入 算 机, 你 每 秒 出 3 次 命 令, 想 必 会 很 不 舒 服 所 以, 你 必 提 前 写 好 你 的 指 令 我 把 些 存 下 来 的 指 令 称 程 序, 写 指 令 并 行 的 活 称 之 程 1.3 理 解 程 在 本 其 他 章 中, 我 把 你 培 养 成 一 名 理 解 程 并 具 一 定 程 能 力 的 人 最 后, 你 会 成 一 个 程 序, 也 不 是 的 但 至 少 你 掌 握 了 如 何 看 待 数 据 ( 信 息 ) 分 析, 并 开 出 解 决 的 程 序 从 某 种 意 上 来, 程 序 的 养 成 需 要 种 技 能 : 首 先, 需 要 掌 握 程 言 (Python) 本 身 熟 悉 和 法 能 准 确 地 拼 写 新 言 中 的, 并 且 掌 握 如 何 使 用 新 言 正 确 地 造 句 其 次, 学 会 故 事 在 写 故 事 的 程 中, 通 文 字 和 句 式 的 合, 向 者 思 想 故 事 的 与 能 力 通 写 作 与 反 得 以 提 高 在 程 中, 程 序 即 故 事, 待 解 决 的 即 的 想 法 当 掌 握 一 种 程 言 ( 如 Python) 之 后, 你 会 学 其 他 程 言, 如 JavaScript 或 者 C++, 就 会 容 易 多 然 新 的 程 言 有 很 多 不 同 的 和 法, 但 你 已 学 会 解 决 的 技 能, 所 有 程 言 本 上 都 是 相 通 的 Python 的 和 句 式 上 手 很 快, 但 要 能 写 出 一 些 的 程 序 来 解 决 一 个 全 新 的, 尚 需 日 磨 授 程 就 像 授 写 作 一 先 程 序 行 和 解, 然 后 写 的 程 序, 接 着 逐 步 写 更 复 的 程 序 当 到 一 定 水 平, 你 就 形 成 了 自 己 的 程 格, 自 然 而 然 地 去, 通 写 程 序 解 决 它 一 旦 修 到 个 程 度, 程 就 成 一 个 愉 悦 且 富 有 造 力 的 程 了 我 从 Python 程 序 的 和 起 第 一 次, 一 定 要 耐 心 学 那 些 的 例 子 1.4 与 句 子 与 人 言 不 同 的 是,Python 的 数 量 上 相 当 少 我 称 些 保 留 字, 它 是 Python 中 具 有 特 殊 意 的 于 Python 来, 程 序 中 出 的 些, 它 有 且 有 一 个 含 等 下 你 在 程, 你 自 己 定 的 称 量 量 命 名 非 常 自 由, 但 有 一 点, 你 不 能 使 用 Python 的 保 留 字 作 量 名 从 某 种 意 上, 我 一 只 狗 会 使 用 一 些 特 殊 的, 比 如 坐 下 停 下 和 拿 来 跟 狗 不 用 些 保 留 字 的, 它 就 会 傻 傻 地 看 着 你, 直 到 你 它 出 保 留 字 例 来, 我 希 望 更 多 的 人 通 散 步 来 促 健 康, 而 大 多 数 狗 听 到 的 可 能 是, 吧 吧 散 步 吧 吧 是 因 在 狗 的 言 中 散 步 是 保 留 字 很 多 人 可 能 得 人 和 猫 之 的 言 没 有 保 留 字 1 Python 的 保 留 字 如 下 : 什 么 要 学 程 10

and del from not while as elif global or with assert else if pass yield break except import print class exec in raise continue finally is return def for lambda try 就 么 多 Python 比 狗 有 素 多 了 当 你 try,python 会 毫 无 差 地 行 try 后 章 会 介 些 保 留 字 及 它 的 适 用 合 在, 我 只 关 注 怎 么 与 Python ( 就 像 人 跟 狗 ) 教 Python 是 件 有 意 思 的 事 情, 把 想 要 的 用 引 号 括 起 来 就 可 以 了 print 'Hello world!' 就 是 我 写 出 的 第 一 个 法 正 确 的 Python 句 以 保 留 字 print 开, 后 面 跟 一 个 文 本 字 符 串, 用 引 号 括 起 来 1.5 与 Python 我 已 掌 握 了 Python 的 一 个 与 一 个 句, 接 下 来 需 要 了 解 如 何 与 Python, 我 的 新 言 技 能 与 Python 之 前, 必 先 在 算 机 上 安 装 Python 件, 学 会 如 何 Python 本 章 包 含 多, 建 看 http://www.pythonlearn.com, 网 站 上 有 Python 在 Mac 和 Windows 系 上 配 置 和 的 明 和 演 示 当 打 开 端 或 者 命 令 行 窗 口, 入 python,python 解 析 器 会 以 交 互 模 式, 如 下 所 示 : Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49) [GCC 4.2.1 (Apple Inc. build 5646)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> >>> 提 示 符 表 示 Python 解 析 器 在, 你 希 望 我 下 一 步 做 什 么? Python 已 准 好 与 你 你 需 要 掌 握 的 是 怎 Python 言, 起 一 个 个 例 子, 你 Python 言 最 的 或 句 子 一 无 所 知, 想 要 使 用 宇 航 的 准 用 ( 喊 ) 宇 航 在 一 个 遥 的 星 球 登, 着 和 个 星 球 的 居 民 用 以 下 句 : >>> I come in peace, please take me to your leader File "<stdin>", line 1 I come in peace, please take me to your leader ^ SyntaxError: invalid syntax >>> 事 情 展 好 像 并 不 利 除 非 你 反 迅 速, 否 个 星 球 的 居 民 可 能 会 拿 矛 刺 向 你, 向 你 吐 口 水, 然 后 把 你 放 在 火 上 烤, 当 成 晚 吃 掉 幸 的 是, 旅 行 你 了 本, 及 翻 到 了 一, 再 一 次 : >>> print 'Hello world!' Hello world! 次 看 起 来 效 果 不, 着 与 他 : 什 么 要 学 程 11

>>> print 'You must be the legendary god that comes from the sky' You must be the legendary god that comes from the sky >>> print 'We have been waiting for you for a long time' We have been waiting for you for a long time >>> print 'Our legend says you will be very tasty with mustard' Our legend says you will be very tasty with mustard >>> print 'We will have a feast tonight unless you say File "<stdin>", line 1 print 'We will have a feast tonight unless you say ^ SyntaxError: EOL while scanning string literal >>> 此, 你 意 到,Python 然 非 常 复 与 强 大, 但 在 法 上 非 常 挑 剔, 并 不 那 么 智 能 中 必 使 用 正 确 的 法 在 某 种 意 上, 当 你 使 用 人 写 的 程 序,Python 就 在 你 和 其 他 程 序 之 充 当 中 人 Python 是 程 序 写 者 将 行 下 去 的 一 种 方 式 在 完 短 短 几 章 之 后, 你 将 成 Python 程 序 中 的 一, 与 你 的 程 序 使 用 者 行 束 与 Python 解 析 器 的 第 一 次 之 前, 你 可 能 要 知 道 如 何 正 确 地 与 个 星 球 的 居 民 再 : >>> good-bye Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'good' is not defined >>> if you don't mind, I need to leave File "<stdin>", line 1 if you don't mind, I need to leave ^ SyntaxError: invalid syntax >>> quit() 你 会 前 个 提 示 是 不 同 的 由 于 if 是 保 留 字,Python 看 到 保 留 字 会 我 想 些 什 么, 但 句 子 的 法 是 的 跟 Python 再 的 正 确 方 法 是, 在 交 互 模 式 的 提 示 符 >>> 后 入 quit() 猜 出 个 命 令 可 能 会 花 一 些, 所 以 手 本 可 能 会 派 上 用 1.6 : 解 器 与 器 Python 是 一 种 高 言, 旨 在 方 便 地 人 行 写, 算 行 取 与 理 其 他 高 言 包 括 :Java C++ PHP Ruby Basic Perl 以 及 JavaScript 等 CPU 里 的 硬 件 并 不 能 理 解 任 何 一 种 高 言 CPU 能 理 解 的 言 称 之 机 器 言 机 器 言 非 常, 坦 白, 写 起 来 非 常 无 聊 它 全 部 由 0 和 1 成 : 01010001110100100101010000001111 11100110000011101010010101101101... 然 机 器 言 表 面 看 起 来 很, 只 有 0 和 1, 但 它 的 法 比 Python 复 得 多 所 以, 很 少 有 程 序 用 机 器 言 程 相 反, 借 助 各 种 翻 器, 程 序 可 以 写 像 Python 或 JavaScript 的 高 言, 些 翻 器 会 将 程 序 成 机 器 言, 再 交 由 CPU 行 因 机 器 言 依 附 于 算 机 硬 件, 所 以 不 能 在 不 同 型 硬 件 之 移 植 使 用 高 言 写 的 程 序 可 以 在 不 同 的 算 机 之 移 植, 通 在 一 台 算 机 上 使 用 不 同 的 器, 或 者 重 新 代, 生 成 一 个 适 合 台 算 机 的 机 器 言 版 本 程 言 的 翻 器 大 体 可 分 :(1) 解 器 与 (2) 器 什 么 要 学 程 12

解 器 取 程 序 所 写 程 序 的 源 代, 解 析 源 代 并 解 指 令 Python 是 一 种 解 器 当 交 互 式 行 Python, 入 一 行 Python 句,Python 就 会 立 即 理 它, 并 做 好 准 我 入 下 一 条 句 Python 句 中 有 一 些 地 方 会 告 Python, 你 想 要 Python 住 等 下 会 用 到 的 一 些 数 据 就 需 要 数 据 挑 一 个 名 称 来 住 它, 之 后 就 可 以 通 个 名 称 来 取 的 数 据 了 我 使 用 量 (variable) 来 代 表 存 的 数 据 >>> x = 6 >>> print x 6 >>> y = x * 7 >>> print y 42 >>> 在 个 例 子 中, 我 Python 住 数 6, 并 将 6 量 x, 以 便 后 使 用 了 确 Python 已 住 个 数, 使 用 print 命 令 打 印 量 x 的 接 下 来, 我 Python 取 量 x 的 并 乘 以 7, 然 后 将 果 新 量 y 最 后, 打 印 出 当 量 y 的 当 前 一 次 入 一 行 命 令,Python 将 其 一 个 句 序 列, 后 面 的 句 可 以 取 前 面 句 的 数 据 四 句 成 的 段 落 以 一 种 有 的 和 有 意 的 序 写, 就 是 我 写 出 的 第 一 个 的 多 行 程 序 如 上 所 示, 解 器 的 本 是 行 交 互 式 器 需 要 将 整 个 程 序 放 在 一 个 文 件 中, 将 高 次 的 源 代 翻 成 低 次 的 机 器 言, 然 后 器 将 生 成 的 机 器 言 放 到 一 个 文 件 中 以 便 后 行 如 果 你 使 用 Windows 系, 些 可 行 的 机 器 言 程 序 通 常 有.exe 或.dll 后, 分 代 表 是 可 行 的 和 可 加 在 Linux 和 Mac 中 没 有 的 后 来 明 确 表 示 文 件 是 否 是 可 行 的 如 果 在 文 本 器 中 打 开 一 个 可 行 文 件, 眼 望 去 完 全 看 不 : ^?ELF^A^A^A^@^@^@^@^@^@^@^@^@^B^@^C^@^A^@^@^@\xa0\x82 ^D^H4^@^@^@\x90^]^@^@^@^@^@^@4^@ ^@^G^@(^@$^@!^@^F^@ ^@^@4^@^@^@4\x80^D^H4\x80^D^H\xe0^@^@^@\xe0^@^@^@^E ^@^@^@^D^@^@^@^C^@^@^@^T^A^@^@^T\x81^D^H^T\x81^D^H^S ^@^@^@^S^@^@^@^D^@^@^@^A^@^@^@^A\^D^HQVhT\x83^D^H\xe8... 机 器 言 的 写 并 不 容 易, 好 在 借 助 解 器 和 器, 能 使 用 Python 或 C 的 高 言 写 程 序 通 解 器 与 器 的, 你 Python 解 器 本 身 有 了 一 些 了 解 那 它 又 是 用 什 么 言 写 的? 是 用 言 写 的? 当 我 入 python, 究 竟 生 了 什 么? Python 的 解 器 是 用 C 言 写 的 你 可 以 http://www.python.org 网 站, 看 Python 解 器 的 源 代, 如 有 你 有 意 愿 改 造 些 源 代 也 是 可 以 的 Python 本 身 就 是 一 个 程 序, 它 被 成 机 器 代 当 你 ( 或 硬 件 供 商 ) 在 算 机 上 安 装 了 Python, 是 上 将 一 份 好 的 Python 程 序 的 机 器 代 拷 到 你 的 算 机 系 在 Windows 中,Python 可 行 的 机 器 代 很 可 能 位 于 以 下 文 件 中 : C:\Python27\python.exe 要 成 一 名 Python 程 序, 你 知 道 些 不 但 在 一 开 始, 花 一 些 解 些, 是 得 的 1.7 写 一 个 程 序 体 Python 功 能 的 最 好 方 式 是 在 Python 解 析 器 中 入 命 令, 但 不 建 采 用 种 方 式 来 解 决 复 的 什 么 要 学 程 13

程, 我 在 文 本 器 里 把 Python 指 令 写 到 一 个 文 件 里, 个 文 件 称 脚 本 一 般 而 言,Python 脚 本 以.py 命 名 尾 行 脚 本, 你 必 告 Python 解 器 脚 本 文 件 的 名 称 在 Unix 或 Windows 命 令 窗 口 中, 你 可 以 入 以 下 代 来 行 hello.py 脚 本 文 件 : csev$ cat hello.py print 'Hello world!' csev$ python hello.py Hello world! csev$ csev$ 是 操 作 系 提 示 符, cat hello.py 是 看 hello.py 文 件 的 内 容, 其 中 包 含 了 字 符 串 打 印 的 一 行 Python 程 序 我 用 Python 解 器, 告 它 从 hello.py 文 件 中 取 源 代, 而 不 是 用 命 令 行 交 互 式 行 Python 代 你 会, 没 有 必 要 在 Python 程 序 文 件 末 尾 加 上 quit() Python 取 源 代 文 件, 到 文 件 末 尾 它 会 自 己 停 止 1.8 什 么 是 程 序? 程 序 的 基 本 定 是, 完 成 特 定 任 的 一 Python 句 序 列 最 的 hello.py 脚 本 也 是 一 个 程 序, 不 只 是 一 行 代 的 程 序 了, 没 多 大 作 用, 但 是 从 格 的 定 上 来, 它 是 一 个 Python 程 序 考 一 个 可 以 被 程 序 解 决 的, 然 后 用 程 序 来 解 决 它, 可 能 是 理 解 程 序 的 最 方 式 假, 你 想 Facebook 上 的 帖 行 社 会 算 方 面 的 研 究, 可 能 感 趣 的 是 帖 中 最 常 用 的 是 什 么 你 可 以 打 印 出 些 帖, 然 后 通 文 本, 从 中 找 最 常 的, 但 需 要 很 而 且 很 容 易 出 通 写 Python 程 序 来 快 速 且 准 确 地 理 个 任, 会 比 明 智, 周 末 就 可 以 做 些 其 他 有 趣 的 事 了 例 来, 以 下 内 容, 是 关 于 一 个 小 丑 和 一 的 文 本, 找 出 出 次 数 最 多 的, 并 它 出 的 次 数 the clown ran after the car and the car ran into the tent and the tent fell down on the clown and the car 想 象 一 下, 要 数 百 万 行 文 本 来 完 成 个 任 会 是 怎 的 情 形 坦 率 地, 学 Python, 写 一 个 Python 程 序 来 的, 要 比 人 工 描 快 得 多 一 个 好 消 息, 我 用 一 个 程 序 解 决 了 在 文 本 文 件 中 找 到 最 常 的 个 我 已 写 好 并 了 个 程 序 在, 我 把 它 交 你 使 用, 就 可 以 省 你 的 一 些 name = raw_input('enter file:') handle = open(name, 'r') text = handle.read() words = text.split() counts = dict() for word in words: counts[word] = counts.get(word,0) + 1 bigcount = None bigword = None for word,count in counts.items(): if bigcount is None or count > bigcount: bigword = word bigcount = count print bigword, bigcount 什 么 要 学 程 14

你 甚 至 不 需 要 知 道 Python 就 可 以 使 用 个 程 序 你 需 要 通 本 第 10 章 来 完 全 理 解 所 用 到 的 Python 程 技 你 在 是 最 用, 只 需 使 用 个 程 序, 你 就 会 于 它 的 明, 感 如 何 你 脱 繁 重 的 手 工 描 你 只 需 入 代, 保 存 成 words.py 文 件 并 行 它, 或 者 也 可 以 从 http://www.pythonlearn.com/code/ 下 源 个 示 例 充 分 体 了 Python 以 及 言 在 你 ( 最 用 ) 与 我 ( 程 序 ) 之 扮 演 的 中 人 角 色 在 安 装 了 Python 的 用 算 机 上,Python 作 一 种 通 用 言, 我 可 以 交 有 用 的 指 令 序 列 ( 即 程 序 ) 因 此, 我 并 不 是 跟 Python 交 流, 而 是 通 Python 与 其 他 人 交 流 1.9 程 序 的 架 后 章 会 介 深 Python 的 句 子 段 落 与 篇 章 我 将 学 Python 的 强 大 功 能, 以 及 如 何 将 些 功 能 合 起 来 建 有 用 的 程 序 程 序 的 造 包 含 一 些 低 次 的 概 念 模 式 些 造 模 式 不 Python 程 序, 而 是 每 一 种 程 言 从 机 器 言 到 高 言 的 通 用 成 部 分 入 : 从 外 部 世 界 取 数 据, 可 以 从 文 件 中 取 数 据, 或 者 从 某 种 感 器, 比 如 麦 克 或 GPS 取 数 据 在 我 最 初 的 程 序 中, 入 是 用 通 入 数 据 出 : 将 程 序 的 果 示 在 屏 幕 上, 或 保 存 在 一 个 文 件, 或 写 入 一 个, 如 声 器 可 以 播 放 音 或 朗 文 字 序 行 : 按 照 脚 本 中 的 句 序, 一 句 接 一 句 行 条 件 行 : 根 据 特 定 条 件 行 或 者 跳 特 定 句 序 列 重 复 行 : 重 复 行 一 些 句, 通 常 也 会 存 在 一 些 化 重 用 : 写 好 一 指 令, 它 命 名, 之 后 在 程 序 中 根 据 需 要 可 以 再 次 使 用 些 指 令 些 听 起 来 好 像 很 容 易, 事 上 并 不 是 那 么 就 好 比, 走 路 很 吧, 把 一 只 脚 放 在 一 只 脚 前 面 程 的 就 是 不 断 造 和 合 些 基 本 元 素, 造 用 有 用 的 西 除 了 重 用 模 式 之 外, 上 面 的 程 序 几 乎 用 到 了 上 面 提 及 的 所 有 模 式 1.10 致 出 的 原 因 在 前 面 与 Python 的 中 已 看 到, 我 写 Python 代 必 非 常 精 确, 很 小 的 偏 差 和 都 会 致 Python 放 弃 行 程 序 初 学 者 通 常,Python 不 能 容 忍 犯, 人 留 下 低 劣 可 恨 与 残 忍 的 印 象 然 Python 看 上 去 与 其 他 人 一, 但 它 能 理 解 初 学 者, 只 是 把 种 抱 怨 化 督 促, 我 更 好 地 写 程 序 不 要 再 Python 老 是 折 磨 我 了 >>> primt 'Hello world!' File "<stdin>", line 1 primt 'Hello world!' ^ SyntaxError: invalid syntax >>> primt 'Hello world' File "<stdin>", line 1 primt 'Hello world' ^ SyntaxError: invalid syntax >>> I hate you Python! File "<stdin>", line 1 I hate you Python! ^ SyntaxError: invalid syntax >>> if you come out of there, I would teach you a lesson File "<stdin>", line 1 什 么 要 学 程 15

if you come out of there, I would teach you a lesson ^ SyntaxError: invalid syntax >>> 与 Python 争 没 什 么 好 它 只 是 一 个 工 具, 没 有 情 感, 它 很 高 随 准 你 服 它 的 信 息 看 起 来 很 苛 刻, 但 些 信 息 帮 助 提 供 索 Python 看 到 了 你 入 的 内 容, 但 不 明 白 你 入 的 是 什 么 Python 更 像 一 只 狗, 无 条 件 你, 只 能 理 解 很 少 的 关, 用 它 那 甜 美 的 表 情 (>>>) 看 着 你, 等 待 你 入 一 些 它 能 理 解 的 西 当 Python 道 : SyntaxError: invalid syntax, 它 只 是 着 尾 巴 : 你 似 乎 了 什 么, 但 我 不 太 明 白, 你 跟 我 (>>>) 当 程 序 得 越 来 越 复, 你 会 遇 到 以 下 三 种 型 的 : 法 : 是 你 遇 到 的 第 一 种, 很 容 易 解 决 法 意 味 着, 你 反 了 Python 的 法 Python 会 尽 可 能 指 出 一 行 句 中 它 所 困 惑 不 能 理 解 的 地 方 和 字 符 法 唯 一 棘 手 的 是, 有 候 程 序 中 需 要 修 改 的 可 能 位 于 Python 所 指 出 困 惑 的 位 置 前 方 所 以,Python 指 出 的 法 位 置 只 是 你 排 的 起 点 : 是 程 序 没 有 法 前 提 下, 句 序 或 句 关 系 存 在 的 一 个 形 象 例 是, 打 开 水 瓶 喝 口 水, 把 它 放 到 包 里, 走 到, 然 后 再 把 水 瓶 盖 上 : 是 程 序 的 法 完 美 且 正 确, 但 无 法 到 期 也 就 是, 程 序 完 全 正 确, 但 它 不 能 做 到 你 想 要 它 做 的 事 一 个 的 例 子, 如 果 你 人 指 路 怎 么 去 一 家 餐, 如 此 : 当 你 走 到 有 加 油 站 的 十 字 路 口, 向 左, 走 一 英 里, 你 的 左 手 有 一 座 色 建 筑, 餐 就 在 那 儿 了 很, 你 的 朋 友 打 来, 他 正 在 一 个, 着 一 个 谷 圈, 并 没 有 看 到 餐 的 志 然 后, 你 : 你 在 加 油 站 左 是 右 了? 他 : 完 全 是 按 你 指 示 的 方 向 走, 我 写 到 上, 在 加 油 站 左, 走 一 英 里 然 后, 你 : 非 常 抱 歉, 然 我 的 方 向 指 示 在 法 上 没, 但 其 中 悲 催 地 包 含 了 一 个 很 小 的 没 有 被 的 于 三 种,Python 会 尽 最 大 努 力 按 照 你 的 要 求 准 确 地 去 行 1.11 学 之 旅 当 循 序 本, 如 果 初 次 遇 到 某 些 概 念 不 能 很 好 理 解, 不 要 担 心 小 候 学, 几 年 只 要 能 出 一 些 可 的 喃 喃 之 音, 不 是 什 么 花 6 个 月 的, 从 能 的 展 到 能 表 的 句 子, 再 用 5 到 6 年 的, 从 句 子 上 升 到 段 落, 的 展 程 是 正 常 的 再 几 年 就 能 依 据 自 身 趣, 独 立 写 出 一 篇 完 整 的 作 文 了 我 希 望 你 能 以 更 快 地 速 度 学 Python, 所 以 有 些 内 容 在 接 下 来 的 几 章 中 会 多 次 涉 及 到 学 一 新 言 需 要 花 去 吸 收 和 理 解, 才 能 做 到 用 自 如 全 景 是 由 一 小 的 片 段 拼 接 起 来 的 我 会 一 再 提 及 一 些 主, 你 看 清 全 景, 可 能 会 致 一 些 混 乱 由 于 的 体 例 是 性 的, 如 果 你 参 加 一, 推 方 式 是 性 的, 但 不 要 受 此 束 前 后 来 回 翻, 行 一 些 略 在 没 有 充 分 理 解 之 前, 跳 有 度 的 内 容, 有 助 于 更 好 的 理 解 程 之 道 通 回 之 前 的 内 容, 或 者 重 做 之 前 做 的, 你 可 能 会 感 收 多, 其 中 些 内 容 可 能 在 你 一 开 始 接 触 得 有 些 解 的 学 第 一 程 言, 通 常 会 有 一 些 得 呼 雀 的 刻 就 像 用 斧 精 心 雕 琢, 一 岩 石 最 在 你 手 中 成 一 尊 美 的 雕 塑 如 果 有 些 事 看 起 来 特 困, 通 宵 熬 夜 耗 着 是 没 有 意 的 休 息 一 下, 打 个, 吃 点 零 食, 向 某 人 ( 可 能 是 你 的 狗 ) 下 你 当 下 遇 到 的, 然 后, 以 全 新 的 眼 光 回 来 再 看 个 我 保, 一 旦 你 从 本 中 学 会 了 程 知, 再 回 看, 你 会 程 是 非 常 和 雅 的 行, 只 是 需 要 花 一 些 去 吸 收 了 1.12 臭 虫 : 程 序 中 的 什 么 要 学 程 16

中 央 理 元 : 所 有 算 机 的 心 我 写 的 件 都 由 它 来 行, 也 称 CPU 或 者 理 器 : 把 高 言 写 的 程 序 翻 成 低 言, 后 行 做 好 准 交 互 模 式 : 在 提 示 符 后 入 命 令 和 表 式, 是 Python 解 器 的 一 种 使 用 方 法 解 : 采 用 一 次 翻 一 行 的 方 式 来 行 高 言 写 的 程 序 低 言 : 一 种 旨 在 便 于 算 机 行 的 程 言, 也 称 机 器 或 言 机 器 代 : 最 接 近 硬 件 的 程 言, 可 直 接 由 中 央 理 元 (CPU) 行 主 存 器 : 存 程 序 和 数 据 关 源 后 主 存 器 的 信 息 会 失 解 析 : 程 序 和 分 析 法 可 移 植 性 : 程 序 的 一 个 属 性, 即 程 序 可 在 不 同 型 的 算 机 上 行 print 句 : 能 Python 解 器 在 屏 幕 上 示 数 据 的 指 令 解 决 : 提 出 一 个, 找 到 解 决 方 法 并 形 成 解 决 方 案 的 程 程 序 : 特 定 算 的 一 指 令 集 提 示 : 程 序 示 一 个 消 息, 等 待 用 的 入 助 存 器 : 存 程 序 和 数 据, 源 关 后 数 据 不 会 失 助 存 器 的 速 度 通 常 比 主 存 器 慢 助 存 器 包 括 磁 器 U 中 的 存 等 : 程 序 本 身 的 含 : 程 序 的 一 种 程 序 并 未 按 照 程 序 意 愿 做 事 源 代 : 程 序 的 高 言 代 1.13 1.1 算 机 的 助 存 器 的 功 能 是 什 么? a) 行 程 序 的 所 有 算 和 b) 在 互 网 上 索 网 c) 期 存 信 息, 甚 至 重 之 后 信 息 不 会 失 d) 接 收 用 的 入 1.2 什 么 是 程 序? 1.3 器 和 解 器 有 什 么 区? 1.4 下 面 个 包 含 了 机 器 代? a) 解 器 b) 什 么 要 学 程 17

c)python 源 文 件 d)word 文 档 1.5 找 出 下 面 代 的 : >>> primt 'Hello world!' File "<stdin>", line 1 primt 'Hello world!' ^ SyntaxError: invalid syntax >>> 1.6 行 以 下 Python 句, 量 X 存 于 何? x = 123 a) 中 央 理 器 b) 主 存 器 c) 助 存 器 d) 入 e) 出 1.7 以 下 程 序 会 出 什 么? x = 43 x = x + 1 print x a)43 b)44 c)x+1 d) 出, 因 x = x + 1 在 数 学 上 不 通 1.8 以 人 作 比, 解 以 下 事 物 :(1) 中 央 理 元,(2) 主 存 器,(3) 助 存 器,(4) 入 和 (5) 出 例 如, 算 机 的 中 央 理 元 相 当 人 体 个 部 位? 1.9 如 何 解 决 法? 1. http://xkcd.com/231/ 什 么 要 学 程 18

第 2 章 量 表 式 与 句 2.1 与 型 是 程 序 的 基 本 成 要 素, 如 一 个 字 母 或 一 个 数 字 目 前 止, 我 接 触 到 的 有 1 2 和 Hello,World! 些 属 于 不 同 的 型 :2 是 整 数, Hello,World! 是 字 符 串 ( 包 含 一 串 字 母 ) 你 ( 或 者 解 器 ) 可 以 根 据 有 无 引 号 来 判 是 否 是 字 符 串 print 句 也 可 以 打 印 整 数 入 python 命 令 解 器 python >>> print 4 4 如 果 不 确 定 一 个 属 于 种 型, 解 器 会 告 你 >>> type('hello, World!') <type 'str'> >>> type(17) <type 'int'> 而 易, 字 符 串 属 于 str 型, 整 数 属 于 int 型 小 数 点 的 数 字 使 用 浮 点 (floating-point) 格 式 表 示, 称 float 型 >>> type(3.2) <type 'float'> 那 么, 像 '17' 和 '3.2' 种 属 于 种 型 呢? 看 起 来 像 数 字, 但 它 和 字 符 串 一 被 放 在 引 号 里 面 >>> type('17') <type 'str'> >>> type('3.2') <type 'str'> 它 是 字 符 串 入 大 的 数 字, 可 能 会 在 每 三 个 数 字 之 加 一 个 逗 号, 例 如,1,000,000 在 Python 中 不 是 一 个 整 数, 但 表 示 是 合 法 的 >>> print 1,000,000 1 0 0 不 是 我 想 要 的!Python 解 器 会 把 1,000,000 当 做 一 个 逗 号 分 隔 的 数 字 序 列, 它 会 把 三 部 分 依 次 打 印 出 来, 中 用 空 格 分 开 是 我 遇 到 的 第 一 个 例 子 : 代 行 不 会 出 任 何 信 息, 但 是 它 并 没 有 做 正 确 的 事 2.2 量 量 表 式 与 句 19

程 言 最 强 大 的 功 能 之 一 体 在 量 的 操 作 能 力 量 是 一 个 的 引 用 名 称 句 用 来 建 新 量 并 其 : >>> message = 'And now for something completely different' >>> n = 17 >>> pi = 3.1415926535897931 个 例 子 列 了 三 种 不 同 型 的 句 第 一 条 句 将 字 符 串 量 message; 第 二 条 句 将 整 数 17 量 n, 第 三 条 句 将 π 的 近 似 量 pi 使 用 打 印 句 出 些 量 的 >>> print n 17 >>> print pi 3.14159265359 量 的 型 就 是 它 所 指 向 的 的 型 >>> type(message) <type 'str'> >>> type(n) <type 'int'> >>> type(pi) <type 'float'> 2.3 量 名 与 关 字 程 序 通 常 会 有 意 的 量 名, 通 量 名 直 地 了 解 量 的 用 途 量 名 不 限 度, 可 以 同 包 含 字 母 和 数 字, 但 是 必 以 字 母 开 使 用 大 写 字 母 也 是 合 法 的, 但 使 用 小 写 字 母 会 更 好 ( 随 后 会 解 原 因 ) 下 划 可 以 出 在 量 名 中 它 常 用 在 含 有 多 个 的 量 名 中, 例 如,my_name 和 airspeed_of_unladen_swallow 量 名 可 以 采 用 下 划 开, 但 一 般 要 避 免 命 名, 除 非 是 写 供 他 人 使 用 的 Python 代 如 果 使 用 不 合 法 的 量 名, 你 就 会 得 到 一 个 法 : >>> 76trombones = 'big parade' SyntaxError: invalid syntax >>> more@ = 1000000 SyntaxError: invalid syntax >>> class = 'Advanced Theoretical Zymurgy' SyntaxError: invalid syntax 76trombones 不 是 合 法 的 量 名, 它 不 是 以 字 母 开 的 more@ 也 是 不 合 法 的, 它 包 含 了 一 个 不 合 法 的 字 符 @ 量 名 class 在 呢? 原 因 在 于,class 是 Python 的 保 留 关 字 Python 解 器 使 用 保 留 关 字 来 程 序 的, 因 此, 保 留 关 字 不 能 用 于 量 名 Python 的 31 个 保 留 关 字 如 下 所 示 1 : 量 表 式 与 句 20

and del from not while as elif global or with assert else if pass yield break except import print class exec in raise continue finally is return def for lambda try 你 可 以 在 手 存 留 一 份 如 果 解 器 指 出 了 一 个 量 名 不 合 法, 而 你 又 不 知 道 什 么, 那 么 一 下 量 名 是 否 在 个 列 表 里 面 2.4 句 句 是 Python 解 器 能 行 的 代 元 我 已 到 个 句 :print 和 assignment 在 交 互 模 式 中 入 一 条 句, 解 器 就 会 行 它 并 打 印 出 果 ( 如 果 有 果 的 ) 程 序 例 如 下 : print 1 x = 2 print x 得 到 以 下 出 果 : 1 2 其 中, 句 没 有 出 果 2.5 算 符 和 算 象 算 符 是 表 示 算 的 一 特 殊 符 号, 例 如, 加 法 与 乘 法 算 符 操 作 的 称 算 象 + - * / 和 ** 五 个 算 符 分 代 表 加 乘 除 和 次 方 的 算, 看 如 下 示 例 : 20+32 hour-1 hour*60+minute minute/60 5**2 (5+9)*(15-7) 除 算 的 果 可 能 不 是 你 所 期 待 的 : >>> minute = 59 >>> minute/60 0 minute 的 是 59, 在 的 算 中,59 除 以 60 是 0.98222, 而 不 是 0 出 种 差 异 的 原 因 在 于,Python 行 的 是 地 板 除 法 (floor division) 2 当 个 算 象 都 是 整 数, 那 么 果 也 是 整 数 地 板 除 法 默 去 掉 小 数 部 分, 因 此 上 面 的 算 果 是 0 如 果 个 算 象 都 是 浮 点 数, 那 么 Python 会 行 浮 点 除 法, 果 就 是 浮 点 数 : 量 表 式 与 句 21

>>> minute/60.0 0.98333333333333328 2.6 表 式 表 式 是 量 和 算 符 的 合 本 身 可 以 是 一 个 表 式, 量 亦 如 此 下 面 都 是 合 法 的 表 式 ( 假 量 x 已 被 ): 17 x x + 17 如 果 在 交 互 模 式 中 入 一 个 表 式, 解 器 就 会 行 它 并 把 果 打 印 出 来 >>> 1 + 1 2 然 而, 在 一 个 程 序 中, 表 式 本 身 并 不 能 做 任 何 事 情! 是 初 学 者 容 易 混 淆 的 一 点 2.1 在 Python 解 器 中 入 下 面 的 句 并 看 果 : 5 x = 5 x + 1 2.7 算 序 当 一 个 表 式 中 出 多 个 算 符, 算 序 按 照 一 定 行 于 数 学 算 符 来,Python 遵 照 数 学 算, 先 括 号 再 次 方 接 着 乘 除 后 加 (PEMDAS) 会 帮 助 你 住 算 序 括 号 有 最 高 算 先, 表 式 按 特 定 序 行 算 括 号 内 的 表 式 先 行 算, 例 如,2 (3-1) 等 于 4, (1+1)**(5-2) 等 于 8 有 候, 括 号 即 便 没 有 改 算 果, 但 可 以 起 来 更 加 方 便, 例 如,(minute 100) / 60 算 的 次 于 括 号, 例 如,2**1+1 等 于 3, 而 不 是 4,3*1**3 等 于 3, 而 不 是 27 乘 法 和 除 法 具 有 相 同 的 先, 高 于 加 法 和 法 例 如,2*3-1 等 于 5, 而 不 是 4,6+4/2 等 于 8, 而 不 是 5 相 同 先 的 算 符 按 从 左 到 右 的 序 依 次 算 例 如,5-3-1 等 于 1, 而 不 是 3 先 算 5-3 得 到 的 2, 然 后 再 1 当 不 能 确 定 算 序, 通 常 使 用 括 号 来 确 保 既 定 的 算 序 2.8 模 算 模 的 算 象 是 整 数, 得 到 的 是 第 一 个 整 数 与 第 二 个 整 数 相 除 的 余 数 在 Python 中, 模 算 符 用 百 分 号 (%) 表 示, 法 与 其 他 算 符 一 致 : >>> quotient = 7 / 3 >>> print quotient 2 >>> remainder = 7 % 3 >>> print remainder 1 量 表 式 与 句 22

7 被 3 所 除 的 商 是 2, 余 数 是 1 模 算 非 常 用 例 来, 你 可 以 一 个 数 是 否 能 被 一 个 数 整 除, 如 果 x%y 的 果 是 0, 那 么 x 能 被 y 整 除 外, 模 算 也 可 以 提 取 出 一 个 数 字 最 右 的 数 位 例 来,x%10 可 以 提 取 出 一 个 数 最 右 的 一 位 数 字 ( 以 10 基 数 ) 同 理,x%100 可 以 提 取 出 一 个 数 最 右 的 位 数 字 2.9 字 符 串 算 符 加 号 的 算 象 是 字 符 串, 它 会 把 字 符 串 首 尾 相 里 不 是 数 学 意 上 的 加 号 例 如 : >>> first = 10 >>> second = 15 >>> print first+second 25 >>> first = '100' >>> second = '150' >>> print first + second 100150 个 程 序 的 出 果 是 100150 2.10 求 用 入 有 候 我 希 望 取 用 通 入 的 Python 提 供 了 一 个 入 函 数 raw_input, 用 来 取 入 3 当 用 个 函 数, 程 序 会 停 行, 等 待 用 的 入 当 用 按 下 回, 程 序 就 恢 复 行,raw_input 函 数 以 字 符 串 形 式 返 回 用 入 的 >>> input = raw_input() Some silly stuff >>> print input Some silly stuff 从 用 取 入 之 前, 最 好 打 印 一 条 提 示 句, 告 用 可 以 入 些 什 么 在 程 序 停 等 待 用 入 之 前, 你 可 以 在 raw_input 中 插 入 一 个 字 符 串 来 提 示 用 >>> name = raw_input('what is your name?\n') What is your name? Chuck >>> print name Chuck 提 示 尾 的 \n 表 示 新 开 辟 一 行, 它 是 一 个 用 于 行 的 特 殊 字 符 一 来, 用 入 的 位 置 出 在 提 示 句 的 下 面 如 果 希 望 用 入 一 个 整 数, 你 可 以 int() 函 数, 将 返 回 的 成 整 数 型 : What...is the airspeed velocity of an unladen swallow? 17 >>> int(speed) 17 >>> int(speed) + 5 22 但 是, 如 果 用 入 的 不 是 数 字 成 的 字 符 串, 那 么 就 会 : 量 表 式 与 句 23

>>> speed = raw_input(prompt) What...is the airspeed velocity of an unladen swallow? What do you mean, an African or a European swallow? >>> int(speed) 随 后 会 介 如 何 理 2.11 注 当 程 序 得 越 来 越 复, 度 也 随 之 增 大 正 的 程 序 代 很 密 集, 常 会 遇 到 看 不 段 代 是 做 什 么 的, 或 者 什 么 要 写 解 决 个, 在 程 序 代 中 加 入 自 然 言 明, 解 段 代 的 作 用, 会 是 一 个 不 的 主 意 些 明 称 注, 它 以 # 号 开 : # compute the percentage of the hour that has elapsed percentage = (minute * 100) / 60 上 面 种 情 况, 注 本 身 占 一 行 你 也 可 以 把 它 加 到 一 行 代 的 末 尾 : percentage = (minute * 100) / 60 # percentage of an hour 从 # 号 开 始 到 一 行 的 最 后, 都 会 被 忽 略 掉, 它 不 会 程 序 生 任 何 影 代 不 著 的 特 征 行 明, 注 非 常 有 用 注 会 帮 助 代 者 搞 清 楚 段 代 的 作 用 注 用 于 代 什 么 写 的 解, 同 有 用 下 面 行 注 明 是 多 余 的, 没 什 么 作 用 : v = 5 # assign 5 to v 而 下 面 的 行 注 包 含 了 有 用 的 信 息 : v = 5 # velocity in meters/second. 清 晰 易 的 量 名 能 少 注 的 使 用, 但 是 量 名 如 果 太, 就 会 使 复 的 表 式 得 更 加, 所 以 需 要 衡 利 弊 2.12 易 的 量 名 只 要 遵 循 量 命 名 的, 避 免 使 用 保 留 字, 量 的 命 名 是 有 很 多 种 的 程 入 段, 你 在 人 的 程 序 和 写 自 己 的 程 序, 量 的 命 名 可 能 会 感 到 困 惑 例 如, 下 面 三 个 程 序 上 是 一 的, 但 是 和 理 解 起 来 差 很 大 a = 35.0 b = 12.50 c = a * b print c hours = 35.0 rate = 12.50 pay = hours * rate 量 表 式 与 句 24

print pay x1q3z9ahd = 35.0 x1q3z9afd = 12.50 x1q3p9afd = x1q3z9ahd * x1q3z9afd print x1q3p9afd Python 解 器 三 个 程 序 的 理 方 式 完 全 一, 但 是 于 者 理 解 起 来 差 异 很 大 者 能 快 速 看 的 是 第 二 个 程 序, 是 因 程 序 了 能 代 表 量 取 含 的 量 名 种 量 命 名 法 称 助 量 命 名 法 助 4 的 意 思 就 是 帮 助 易 于 的 量 名, 有 助 于 我 住 当 初 建 个 量 是 了 做 什 么 看 起 来 不, 使 用 助 量 命 名 法 是 一 个 好 主 意, 但 可 能 也 会 初 学 者 解 析 与 理 解 代 上 生 面 影 由 于 初 学 者 可 能 没 有 全 Python 的 31 个 保 留 字, 如 果 量 名 中 包 含 太 多 描 述 性 的, 精 心 命 名 的 量 看 上 去 会 像 是 Python 言 的 一 部 分, 初 学 者 理 解 上 造 成 干 下 面 行 的 Python 代 了 循 循 将 在 第 5 章 介, 里 猜 猜 行 代 的 含 : for word in words: print word 行 上 面 的 代 会 生 什 么?for word in 等 几 个 中 些 是 保 留 字, 些 是 量 名?Python 能 理 解 的 基 本 含? 初 学 者 很 分 辨 出 代 中 些 部 分 必 照 抄 示 例 中 的, 而 些 部 分 是 可 以 自 主 的 下 面 的 代 和 上 面 的 代 上 是 一 的 : for slice in pizza: print slice 通 察 段 代, 初 学 者 可 以 容 易 地 分 辨 些 是 Python 保 留 字, 些 是 程 序 自 己 定 的 量 名 而 易,Python 不 能 理 解 pizza 和 slice 之 的 差, 上 就 是 一 个 披 可 以 切 成 很 多 如 果 程 序 要 取 数 据 并 在 数 据 中 找,pizza 和 slice 是 不 容 易 住 的 量 名 它 作 量 名 会 偏 离 程 序 的 本 意 不 了 多 久, 你 会 熟 悉 最 常 用 的 保 留 字 并 在 程 序 中 注 意 到 它 : for word in words: print word 段 Python 代 中 for in print 和 : 加 粗 示, 程 序 自 己 定 的 量 名 不 加 粗 很 多 文 本 器 支 持 Python 法, 它 会 使 用 不 同 的 色 来 保 留 字, 你 能 方 便 地 区 分 保 留 字 与 量 名 熟 悉 一 段 后, 你 就 会 很 快 地 区 分 些 是 保 留 字, 些 是 量 名 2.13 最 容 易 出 的 法 是 不 合 法 的 量 名, 例 如,class 和 yield 是 保 留 字, 或 者 包 含 不 合 法 字 符 的 odd~job 和 US$ 如 果 量 名 中 存 在 空 格,Python 会 它 是 没 有 算 符 的 个 算 象 : >>> bad name = 5 SyntaxError: invalid syntax 法 的 提 示 信 息 提 供 不 了 什 么 帮 助 最 常 的 信 息 是 SyntaxError: invalid syntax 和 SyntaxError: invalid token, 量 表 式 与 句 25

条 都 没 有 提 供 什 么 有 价 的 信 息 最 常 遇 到 的 行 是 use before def;, 个 的 意 思 是 使 用 了 一 个 没 有 的 量 种 情 况 容 易 出 在 量 名 拼 写 的 情 况 : >>> principal = 327.68 >>> interest = principle * rate NameError: name 'principle' is not defined 量 名 区 分 大 小 写, 例 如,LaTeX 和 latex 是 不 一 的 最 容 易 出 的 是 算 序 例 来,\(\dfrac{1}{2π} \) 可 能 会 写 成 : >>> 1.0 / 2.0 * pi 个 句 首 先 行 除 法 算, 得 到 的 果 是 π/2, 然 跟 \( \dfrac{1}{2π} \) 不 是 一 回 事!Python 并 不 明 白 个 表 式 是 什 么 意 思 种 情 况 下 然 不 会, 但 算 果 是 的 2.14 : 量 予 一 个 的 句 接 : 将 个 算 象 首 尾 相 接 注 : 程 序 里 面 包 含 的 信 息, 旨 在 帮 助 其 他 程 序 ( 或 者 看 源 代 的 人 ) 理 解 程 序, 不 会 程 序 的 行 生 任 何 影 求 : 表 式 行 算, 得 到 一 个 表 式 : 量 算 符 和 的 合, 表 示 一 个 果 浮 点 : 有 小 数 部 分 的 数 地 板 除 法 : 截 掉 数 相 除 所 得 果 的 小 数 部 分 的 一 种 除 法 算 整 数 型 : 代 表 整 数 型 关 字 :Python 解 器 用 来 解 析 程 序 的 保 留 字 量 命 名 不 可 使 用 保 留 字, 例 如,if def 与 while 等 助 法 : 一 种 助 的 方 法 通 常 使 用 易 的 量 名 来 帮 助 我 理 解 量 本 身 包 含 的 内 容 模 算 : 用 百 分 号 (%) 表 示, 求 数 相 除 的 余 数 算 象 : 算 符 操 作 的 象 算 符 : 能 行 算 的 一 特 殊 符 号, 例 如, 加 法 乘 法 和 字 符 串 接 算 先 : 一 算, 用 来 定 多 个 算 符 和 算 象 的 表 式 中 算 行 的 次 序 句 : 包 含 指 令 和 行 的 一 段 代 目 前 止, 我 到 了 句 和 打 印 句 字 符 串 : 由 字 符 序 列 成 的 数 据 型 型 : 表 示 一 目 前 止, 我 到 了 整 数 (int), 浮 点 数 (float) 和 字 符 串 (str) 量 表 式 与 句 26

: 数 据 的 基 本 位, 例 如, 程 序 中 可 以 操 作 的 数 字 或 字 符 串 量 : 一 个 的 引 用 名 称 2.15 2.2 使 用 raw_input 写 一 个 程 序, 提 示 用 入 姓 名, 然 后 打 印 出 迎 Enter your name: Chuck Hello Chuck 2.3 写 一 个 程 序, 用 入 工 和 薪, 然 后 算 出 工 Enter Hours: 35 Enter Rate: 2.75 Pay: 96.25 不 用 担 心 果 是 否 精 确 到 小 数 点 后 位 如 果 需 要 精 确 到 小 数 点 后 位, 可 以 使 用 Python 内 置 的 round 函 数 2.4 行 下 面 的 句 : width = 17 height = 12.0 写 出 以 下 表 式 的 及 的 型 1. width/2 2. width/2.0 3. height/3 4. 1 + 2 * 5 使 用 Python 解 器 你 的 果 是 否 正 确 2.5 写 一 个 程 序, 用 入 氏 温 度, 然 后 将 其 化 成 氏 温 度, 最 后 将 化 后 的 温 度 打 印 出 来 1. Python 3.0 中,exec 不 再 是 保 留 关 字,nonlocal 是 新 的 保 留 关 字 2. Python 3.0 中, 做 除 法 的 果 是 浮 点 数 新 的 算 符 // 做 整 数 除 法 3. Python 3.0 中, 个 函 数 称 input 4. " 助 " 的 有 关 介, 参 http://en.wikipedia.org/wiki/mnemonic 量 表 式 与 句 27

第 3 章 条 件 行 3.1 布 表 式 布 表 式 是 具 有 真 或 假 状 的 一 种 表 式 == 算 符 用 来 比 个 算 象, 若 者 相 等 返 回 True, 否 返 回 False: >>> 5 == 5 True >>> 5 == 6 False True 和 False 是 布 型 的 个 取, 它 不 是 字 符 串 : >>> type(true) <type 'bool'> >>> type(false) <type 'bool'> == 算 符 是 比 算 符 中 的 一 个, 其 他 的 比 算 符 如 下 : x!= y x > y x < y x >= y x <= y x is y x is not y # x is not equal to y # x is greater than y # x is less than y # x is greater than or equal to y # x is less than or equal to y # x is the same as y # x is not the same as y 然 你 可 能 很 熟 悉 些 算 符, 但 要 注 意 些 Python 符 号 并 不 等 同 于 数 学 符 号 一 个 常 的 是 用 等 号 (=), 而 没 有 用 双 等 号 (==) 住,= 是 算 符,== 是 比 算 符 不 存 在 =< 或 => 的 算 符 3.2 算 符 算 符 包 括 and( 与 ) or( 或 ) 与 not( 非 ) 三 种 些 算 符 的 与 它 的 英 文 含 相 似 例 如, x > 0 and x < 10 若 x 大 于 0 且 小 于 10, 真 若 n%2 == 0 or n%3 == 0 其 中 有 一 个 条 件 真, 即 个 数 字 能 被 2 或 3 整 除, 真 not 算 符 是 表 示 否 定 的 布 表 式 若 x > y 假, 即 x 小 于 或 者 等 于 y, 那 么 not (x > y) 真 格, 算 符 的 算 象 是 布 表 式, 但 在 Python 中 并 不 是 很 格 任 何 非 零 数 字 都 可 看 作 是 真 >>> 17 and True True 种 灵 活 性 的 存 在 是 有 用 的, 但 也 会 生 一 些 微 妙 的 困 惑 除 非 你 清 楚 自 己 在 做 什 么, 否 不 要 乱 用 条 件 行 28

3.3 条 件 行 了 写 出 有 用 的 程 序, 几 乎 是 需 要 根 据 条 件, 修 改 程 序 相 的 行 条 件 句 予 我 种 能 力 最 的 条 件 形 式 是 if 句 : if x > 0 : print 'x is positive' if 句 后 的 布 表 式 称 条 件 if 句 的 末 尾 用 冒 号 (:),if 句 之 后 的 句 要 若 条 件 真, 那 么 的 句 得 以 行 若 条 件 假, 那 么 的 句 就 会 被 跳 if 句 与 for 循 1 的 函 数 定 具 有 相 同 的 句 由 一 个 以 冒 号 (:) 束 的 行 和 随 后 的 一 个 代 区 域 成 由 于 包 含 多 行, 的 句 被 称 复 合 句 句 内 没 有 句 的 数 量 限 制, 但 至 少 要 有 一 行 有 候, 空 白 的 句 也 是 有 用 的, 通 常 是 未 写 的 代 留 空 在 种 情 况 下, 使 用 pass 句, 表 示 什 么 也 不 做 if x < 0 : pass # need to handle negative values! 如 果 在 Python 解 器 里 入 一 个 if 句, 提 示 符 会 从 三 个 > 成 三 个., 表 明 正 在 一 个 句 内, 如 下 所 示 : >>> x = 3 >>> if x < 10:... print 'Small'... Small >>> 3.4 分 支 行 if 句 的 第 二 种 形 式 是 行 句 中 存 在 种 可 能, 条 件 决 定 了 行 一 种 法 如 下 : if x%2 == 0 : print 'x is even' else : print 'x is odd' 若 x 除 以 2 的 余 数 0, x 是 偶 数, 程 序 就 行 第 一 个 print 句, 示 x is even 若 余 数 不 0, else 之 后 的 第 二 个 print 条 件 行 29

句 得 以 行 由 于 条 件 必 真 或 假, 所 以 条 句 中 有 一 条 会 被 行 些 句 称 行 流 程 中 的 分 支 3.5 式 条 件 有 候 存 在 种 以 上 的 可 能, 那 么 就 需 要 个 以 上 的 分 支 式 条 件 可 以 理 种 情 况 elif 是 else if 的 写, 表 示 又 有 一 个 分 支 将 被 行 elif 句 没 有 数 量 限 制 如 果 有 一 个 else 子 句, 那 它 必 是 最 后 一 个, 但 是 else 子 句 不 是 必 的 if choice == 'a': print 'Bad guess' elif choice == 'b': print 'Good guess' elif choice == 'c': print 'Close, but not correct' 依 次 每 个 条 件 如 果 第 一 个 假, 就 第 二 个, 以 此 下 去 如 果 其 中 一 个 条 件 真, 行 相 的 分 支, 至 此 句 束 即 使 不 止 一 个 条 件 真, 也 只 行 第 一 个 真 的 分 支 3.6 嵌 套 条 件 一 个 条 件 句 也 可 以 嵌 套 到 一 个 条 件 句 中 我 可 以 写 出 三 分 条 件 的 例 子 : 条 件 行 30

if x == y: print 'x and y are equal' else: if x < y: print 'x is less than y' else: print 'x is greater than y' 外 面 的 条 件 句 包 含 了 个 分 支 第 一 条 分 支 包 含 了 一 个 句 第 二 条 分 支 包 含 了 一 个 由 个 分 支 成 的 if 句 个 分 支 都 是 句, 然 个 分 支 包 含 条 件 句, 但 它 都 是 句 然 句 得 清 晰, 但 是 嵌 套 条 件 是 很 快 速 地 一 般 情 况 下, 是 尽 量 避 免 使 用 算 符 通 常 提 供 一 种 方 法 来 化 嵌 套 条 件 句 例 如, 使 用 个 条 件 改 写 以 下 代 : if 0 < x: if x < 10: print 'x is a positive single-digit number.' 当 个 条 件 都 足,print 句 才 会 行 使 用 and 算 符 也 能 到 相 同 的 效 果 : if 0 < x and x < 10: print 'x is a positive single-digit number.' 3.7 try 与 except 异 常 捕 之 前 我 看 到 一 段 代, 使 用 raw_input 和 int 函 数 取 和 解 析 用 入 的 整 数 由 此 来 的 潜 在 危 是 : >>> speed = raw_input(prompt) What...is the airspeed velocity of an unladen swallow? What do you mean, an African or a European swallow? >>> int(speed) ValueError: invalid literal for int() >>> 在 Python 解 器 中 行 些 句, 提 示, 然 后 会 新 起 一 行, 等 待 下 一 条 句 的 入 如 果 把 段 代 放 在 Python 脚 本 文 件 中, 当 生, 脚 本 的 行 会 立 即 停 止 在 一 行, 并 返 回 消 息, 之 后 的 句 不 条 件 行 31

会 被 行 inp = raw_input('enter Fahrenheit Temperature:') fahr = float(inp) cel = (fahr - 32.0) * 5.0 / 9.0 print cel 如 果 我 行 段 代, 入 一 个 无 效 的, 它 会 停 止 行, 并 返 回 一 个 不 友 好 的 信 息 : python fahren.py Enter Fahrenheit Temperature:72 22.2222222222 python fahren.py Enter Fahrenheit Temperature:fred Traceback (most recent call last): File "fahren.py", line 2, in <module> fahr = float(inp) ValueError: invalid literal for float(): fred Python 内 置 了 try/except 条 件 行, 用 来 解 决 意 料 之 中 和 意 料 之 外 的 你 知 道 程 序 可 能 存 在, 希 望 在 生 增 加 一 些 句, try 和 except 就 派 上 用 了 如 果 没 有 出, 些 外 的 句 (except 句 ) 就 会 被 忽 略 掉 你 可 以 把 Python 的 try 和 except 功 能 看 作 是 程 序 的 保 温 度 程 序 重 新 写 如 下 : inp = raw_input('enter Fahrenheit Temperature:') try: fahr = float(inp) cel = (fahr - 32.0) * 5.0 / 9.0 print cel except: print 'Please enter a number' Python 首 先 行 try 句 如 果 一 切 利, 它 就 会 跳 except 句 如 果 在 try 句 里 生 意 外,Python 就 会 跳 出 try 句, 行 except 句 python fahren2.py Enter Fahrenheit Temperature:72 22.2222222222 python fahren2.py Enter Fahrenheit Temperature:fred Please enter a number 用 try 句 理 异 常 的 行 称 异 常 捕 个 示 例 中 except 子 句 打 印 了 一 条 提 示 信 息 一 般 来, 捕 捉 到 异 常, 就 是 你 一 个 机 会 去 解 决 它, 或 者 是 再 一 次, 至 少 程 序 能 正 常 束 3.8 表 式 的 短 路 估 当 Python 理 如 x > = 2 and (x / y)> 2 的 表 式, 从 左 至 右 行 判 断 根 据 and 的 含, 如 果 x 小 于 2, 表 式 x>=2 假, 那 么 整 个 表 式 即 假, 不 管 后 面 的 (x / y)> 2 的 判 断 是 真 或 假 当 Python 表 式 剩 余 部 分 的 判 断 没 有 意 了, 它 就 停 止 剩 余 部 分 的 判 断 在 已 知 表 式 整 体 果 的 情 况 下 停 止 判 断, 称 短 路 估 条 件 行 32

看 起 来 是 一 个, 短 路 行 来 了 一 种 灵 活 的 理 方 式, 称 守 者 模 式 如 下 是 Python 解 器 中 的 一 段 代 : >>> x = 6 >>> y = 2 >>> x >= 2 and (x/y) > 2 True >>> x = 1 >>> y = 0 >>> x >= 2 and (x/y) > 2 False >>> x = 6 >>> y = 0 >>> x >= 2 and (x/y) > 2 Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: integer division or modulo by zero >>> 第 三 次 算 出 了 由 于 y 等 于 0,Python 算 (x/y) 出 行 但 是, 第 二 次 算 没 有 出 由 于 表 式 第 一 部 分 x > = 2 判 断 假, 所 以 根 据 短 路, (x / y) 根 本 没 有 被 行, 所 以 没 有 我 可 以 在 生 之 前, 策 略 性 地 放 置 一 个 守 估, 代 如 下 : >>> x = 1 >>> y = 0 >>> x >= 2 and y!= 0 and (x/y) > 2 False >>> x = 6 >>> y = 0 >>> x >= 2 and y!= 0 and (x/y) > 2 False >>> x >= 2 and (x/y) > 2 and y!= 0 Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: integer division or modulo by zero >>> 第 一 个 表 式 中 x > = 2 假, 所 以 在 and 之 前 判 断 就 停 止 了 第 二 个 表 式 中 x > = 2 真, 但 y!= 0 假, 所 以 (x/y) 没 有 机 会 得 到 判 断 第 三 个 表 式 中 y!= 0 位 于 (x/y) 之 后, 所 以 个 表 式 的 判 断 失 了 第 二 个 表 式 中 y!= 0 作 一 个 守, 确 保 y 不 等 于 0 只 行 (x/y) 3.9 当 生,Python 的 追 踪 (Traceback) 示 很 多 信 息, 但 有 可 能 消 息 多, 特 是 中 有 很 多 的 情 况 其 中 最 有 用 的 部 分 是 : 的 型 是 什 么 生 的 位 置 法 通 常 很 容 易 找 到, 但 也 存 在 一 些 陷 空 格 非 常 棘 手, 由 于 空 格 和 制 表 符 是 不 可 的, 常 常 会 被 忽 >>> x = 5 >>> y = 6 File "<stdin>", line 1 y = 6 ^ SyntaxError: invalid syntax 条 件 行 33

个 例 子 中 出 在 第 二 行 只 用 了 一 个 空 格 但 是 消 息 指 向 了 y, 其 是 一 种 一 般 情 况 下, 信 息 会 示 在 何 被, 但 是 可 能 会 在 所 示 的 代 之 前, 有 候 会 在 前 一 行 行 也 是 如 此 假 用 分 算 信 噪 比, 公 式 是 \(SNR~{db} = 10 log~{10}(\frac{p~{signal}}{p~{noise}})\),python 代 如 下 : import math signal_power = 9 noise_power = 10 ratio = signal_power / noise_power decibels = 10 * math.log10(ratio) print decibels 但 是 当 你 行 段 代, 就 会 收 到 如 下 信 息 2 : Traceback (most recent call last): File "snr.py", line 5, in? decibels = 10 * math.log10(ratio) OverflowError: math range error 信 息 示 第 5 行 出, 但 那 一 行 没 有 了 找 到 真 正 的, 将 ratio 打 印 出 来 可 能 会 有 用 原 来 是 ratio 0, 出 在 第 4 行, 原 因 是 数 相 除 采 用 的 是 地 板 除 法 ( 只 取 整 数 ) 解 决 方 法 是 用 浮 点 数 表 示 信 号 功 率 和 噪 声 功 率 一 般 情 况 下, 信 息 会 告 你 出 在, 但 个 出 位 置 并 不 准 确 3.10 主 体 : 复 合 句 中 的 一 句 布 表 式 : 取 只 有 真 (True) 或 假 (False) 其 中 之 一 的 表 式 分 支 : 条 件 句 中 可 供 的 一 句 式 条 件 : 有 多 个 可 分 支 的 条 件 句 比 算 符 : 算 象 行 比 的 一 种 算 符, 包 括 ==!= > < >=, 和 <= 条 件 句 : 根 据 某 些 条 件 来 控 制 程 序 行 序 的 句 条 件 : 条 件 句 中 的 布 表 式, 用 来 决 定 行 一 个 分 支 复 合 句 : 含 有 部 和 主 体 的 一 句 代 部 以 冒 号 (:) 尾 代 主 体 相 于 代 部 行 守 模 式 : 通 外 的 比 来 造 表 式, 充 分 利 用 短 路 行 算 符 : 合 布 表 式 的 算 符, 包 括 and or 和 not 嵌 套 条 件 : 一 个 条 件 句 作 一 个 条 件 句 的 分 支 追 踪 : 正 在 行 的 函 数 列 表, 当 出 异 常, 在 屏 幕 上 示 出 来 短 路 : 在 判 断 表 式 的 程 中, 如 果 Python 已 知 道 了 最 果, 会 停 止, 不 会 剩 余 的 表 式 行 判 断 条 件 行 34

3.11 3.1 重 写 薪 水 算 公 式, 如 果 工 工 作 超 40 小, 按 平 常 薪 水 的 1.5 倍 支 付 Enter Hours: 45 Enter Rate: 10 Pay: 475.0 3.2 用 try 和 except 重 写 支 付 程 序, 程 序 可 以 正 常 理 非 数 字 入 的 情 况, 如 果 是 非 数 字 入, 打 印 消 息 并 退 出 程 序 以 下 是 程 序 的 种 行 果 : Enter Hours: 20 Enter Rate: nine Error, please enter numeric input Enter Hours: forty Error, please enter numeric input 3.3 写 一 个 程 序, 提 示 分 数 在 0.0 和 1.0 之 如 果 分 数 超 出 个 范 打 印 出 如 果 分 数 在 0.0 和 1.0 之, 使 用 下 面 的 表 格 打 印 分 数 : Score Grade >= 0.9 A >= 0.8 B >= 0.7 C >= 0.6 D < 0.6 F Enter score: 0.95 A Enter score: perfect Bad score Enter score: 10.0 Bad score Enter score: 0.75 C Enter score: 0.5 F 重 复 行 个 程 序, 不 同 的 入 1. 第 4 章 介 函 数, 第 5 章 介 循 2. Python3.0 中, 不 再 出 消 息 即 使 是 整 数 象, 除 法 算 符 行 的 也 是 浮 点 除 法 条 件 行 35

第 4 章 函 数 4.1 函 数 用 程 中 的 函 数 是 行 算 的 一 个 命 名 句 序 列 当 定 函 数, 需 要 指 定 函 数 名 和 句 序 定 好 之 后, 通 函 数 名 就 可 以 用 函 数 之 前 我 到 一 个 函 数 示 例 : >>> type(32) <type 'int'> 个 函 数 的 名 称 是 type 括 号 里 面 的 表 式 称 函 数 的 参 数 参 数 可 以 是 一 个 或 量, 作 函 数 的 入 type 函 数 的 作 用 是 示 参 数 的 型 一 般 而 言, 函 数 取 参 数, 然 后 返 回 果 个 果 称 返 回 4.2 内 置 函 数 Python 提 供 了 很 多 重 要 的 内 置 函 数, 不 需 要 我 先 定 就 可 以 使 用 Python 开 者 定 了 解 决 常 的 函 数 集, 内 置 在 Python 中, 供 我 使 用 max 函 数 和 min 函 数 分 求 得 一 个 列 表 中 的 最 大 和 最 小 : >>> max('hello world') 'w' >>> min('hello world') ' ' >>> max 函 数 告 我, 个 字 符 串 中 最 大 的 字 符 是 ( w ),min 函 数 告 我 个 字 符 串 中 最 小 的 字 符 是 空 格 符 一 个 常 用 的 内 置 函 数 是 len 函 数, 它 能 返 回 参 数 的 度 如 果 len 函 数 的 参 数 是 一 个 字 符 串, 那 么 它 返 回 的 是 个 字 符 串 的 字 符 数 >>> len('hello world') 11 >>> 些 函 数 不 可 用 于 字 符 串, 能 操 作 其 他 数 据 型, 后 章 会 涉 及 到 你 可 以 将 内 置 函 数 比 保 留 字, 例 来, 不 要 使 用 max 作 量 名 4.3 型 函 数 Python 提 供 了 将 一 种 型 成 一 种 型 的 内 置 函 数 在 允 的 情 况 下,int 函 数 能 把 任 何 其 他 型 的 化 成 整 数 型, 如 果 不 能 就 会 : >>> int('32') 32 函 数 36

>>> int('hello') ValueError: invalid literal for int(): Hello int 函 数 能 将 浮 点 型 成 整 数 型, 但 是 它 不 行 四 舍 五 入, 只 是 直 接 去 掉 小 数 部 分 : >>> int(3.99999) 3 >>> int(-2.3) -2 float 函 数 能 把 整 数 型 和 字 符 串 型 成 浮 点 型 : >>> float(32) 32.0 >>> float('3.14159') 3.14159 str 函 数 能 把 入 的 参 数 成 字 符 串 型 : >>> str(32) '32' >>> str(3.14159) '3.14159' 4.4 随 机 数 既 定 入 的 情 况 下, 大 部 分 的 算 机 程 序 每 次 都 会 生 相 同 的 出, 也 就 是 是 板 上 的 事 情 一 般 而 言, 确 定 性 是 好 的, 我 希 望 同 一 个 算 法 生 相 同 的 果 然 而, 有 些 候 我 希 望 算 机 具 不 确 定 性, 比 如 游 就 是 一 个 典 型 例 子, 当 然 有 很 多 其 他 例 子 一 个 程 序 完 全 于 不 确 定 状, 很 做 到 但 是, 有 一 些 方 法 可 以 它 看 起 来 具 有 不 确 定 性 一 种 方 法 是 利 用 算 法 生 随 机 数 随 机 数 并 不 是 真 正 的 随 机 数, 原 因 在 于 它 是 利 用 确 定 的 算 法 算 出 来 的 看 些 数 字 并 不 会 它 和 真 正 的 随 机 数 有 什 么 不 同 随 机 数 模 提 供 了 随 机 数 生 成 的 函 数, 以 下 称 random random 函 数 返 回 一 个 介 于 0.0-1.0 的 随 机 浮 点 数 ( 包 括 0.0, 但 不 包 括 1.0) 每 次 用, 你 会 得 到 一 串 的 数 字 例 来, 行 下 面 的 循 句 : import random for i in range(10): x = random.random() print x 程 序 生 成 了 10 个 介 于 0.0-1.0 之 但 不 包 括 1.0 的 随 机 数 0.301927091705 0.513787075867 0.319470430881 0.285145917252 0.839069045123 0.322027080731 0.550722110248 函 数 37

0.366591677812 0.396981483964 0.838116437404 4.1 行 以 下 程 序 并 察 得 到 的 果, 不 妨 多 行 几 次 看 看 random 函 数 只 是 多 随 机 数 函 数 中 的 一 个 randint 函 数 入 个 整 数 参 数, 并 返 回 介 于 个 参 数 之 的 整 数 ( 包 括 个 参 数 在 内 ) >>> random.randint(5, 10) 5 >>> random.randint(5, 10) 9 取 得 一 中 的 随 机 元 素, 可 以 使 用 下 面 的 程 序 : >>> t = [1, 2, 3] >>> random.choice(t) 2 >>> random.choice(t) 3 random 模 提 供 了 从 分 布 函 数 中 提 取 随 机 的 函 数, 包 括 高 斯 函 数 指 数 函 数 伽 函 数 等 4.5 数 学 函 数 Python 的 math 模 提 供 了 很 多 常 的 数 学 函 数 在 使 用 之 前 要 入 相 的 包 : >>> import math 条 句 建 了 一 个 名 math 的 模 象 如 果 将 个 模 象 打 印 出 来, 就 会 得 到 关 于 它 的 一 些 信 息 : >>> print math <module 'math' from '/usr/lib/python2.5/lib-dynload/math.so'> 个 模 象 包 括 了 模 中 定 的 函 数 和 量 了 使 用 其 中 的 函 数, 你 必 指 定 模 名 和 函 数 名, 用 点 隔 开, 也 就 是 英 文 的 句 号 种 格 式 叫 做 点 (dot notation) >>> ratio = signal_power / noise_power >>> decibels = 10 * math.log10(ratio) >>> radians = 0.7 >>> height = math.sin(radians) 第 一 个 例 子 是 算 以 10 底 的 信 噪 比 的 数 math 模 提 供 了 log 函 数 用 来 求 以 e 底 的 数 第 二 个 例 子 用 了 正 弦 函 数 量 名 字 出 了 提 示, 除 了 正 弦 函 数, 有 余 弦, 正 切 等 其 他 三 函 数 都 采 用 弧 度 作 参 数 将 度 数 成 弧 度 的 算 是 除 以 360, 然 后 乘 以 2π: >>> degrees = 45 >>> radians = degrees / 360.0 * 2 * math.pi >>> math.sin(radians) 函 数 38

0.707106781187 math.pi 表 式 从 math 模 中 取 得 量 pi 的 个 量 是 π 的 一 个 近 似, 保 留 了 小 数 点 后 15 位 数 用 你 的 平 面 几 何 知, 与 2 的 平 方 根 再 除 以 2 的 果 行 比, 程 序 出 是 否 正 确 >>> math.sqrt(2) / 2.0 0.707106781187 4.6 定 新 函 数 目 前 止, 我 只 是 使 用 了 Python 的 内 置 函 数, 除 此 之 外 也 可 以 自 定 新 函 数 通 定 函 数 名 和 一 句 序 列 来 定 一 个 新 函 数, 然 后 在 行 用 个 函 数 一 旦 定 了 一 个 函 数, 程 序 中 可 以 重 复 使 用 def print_lyrics(): print "I'm a lumberjack, and I'm okay." print 'I sleep all night and I work all day.' def 是 用 来 定 函 数 的 保 留 关 字 个 函 数 的 名 称 是 print_lyrics 函 数 命 名 与 量 命 名 的 基 本 上 是 一 的 字 母 数 字 以 及 一 些 符 号 是 合 法 的, 但 是 函 数 名 的 第 一 个 字 符 不 能 是 数 字 不 能 使 用 保 留 关 字 命 名 函 数, 也 要 避 免 函 数 名 和 量 名 相 同 函 数 名 后 面 的 空 括 号 表 明 个 函 数 没 有 指 定 参 数 接 下 来, 我 会 定 有 参 数 的 函 数 函 数 定 的 第 一 行 叫 做 函 数, 剩 余 的 部 分 叫 做 函 数 体 函 数 必 以 冒 号 束, 函 数 体 必 按 照 例, 一 般 4 个 空 格 函 数 体 可 以 包 括 任 意 数 量 的 句 print 句 要 出 的 字 符 串 放 在 双 引 号 里 面 引 号 和 双 引 号 作 用 是 一 的 除 了 在 字 符 串 中 也 有 引 号 的 冲 突 情 况 之 外, 大 多 数 人 会 使 用 引 号 如 果 你 在 Python 交 互 模 式 中 定 函 数, 解 器 会 打 印 省 略 号 ( ) 表 明 函 数 定 没 有 束 >>> def print_lyrics():... print "I'm a lumberjack, and I'm okay."... print 'I sleep all night and I work all day.'... 函 数 定 的 束 方 式 是 入 一 个 空 行 ( 当 然, 在 程 序 文 件 中 不 是 必 的 ) 定 函 数 的 同 也 会 建 一 个 和 函 数 名 相 同 的 量 名 >>> print print_lyrics <function print_lyrics at 0xb7e99e9c> >>> print type(print_lyrics) <type 'function'> print_lyrics 的 是 一 个 函 数 象, 它 的 型 是 函 数 用 自 定 函 数 与 用 内 置 函 数 的 法 是 一 的 : >>> print_lyrics() 函 数 39

I'm a lumberjack, and I'm okay. I sleep all night and I work all day. 函 数 定 好 之 后, 就 可 以 在 其 他 函 数 中 使 用 例 如, 了 重 复 用 之 前 的 函 数, 你 可 以 写 一 个 repeat_lyrics 函 数 : def repeat_lyrics(): print_lyrics() print_lyrics() 然 后 用 个 函 数 : >>> repeat_lyrics() I'm a lumberjack, and I'm okay. I sleep all night and I work all day. I'm a lumberjack, and I'm okay. I sleep all night and I work all day. 中 歌 曲 可 不 是 填 的 4.7 定 与 用 法 将 前 面 的 代 片 段 合 在 一 起, 完 整 的 程 序 如 下 : def print_lyrics(): print "I'm a lumberjack, and I'm okay." print 'I sleep all night and I work all day.' def repeat_lyrics(): print_lyrics() print_lyrics() repeat_lyrics() 个 程 序 包 含 了 个 自 定 函 数 :print_lyrics 和 repeat_lyrics 函 数 定 会 像 其 他 句 一 行, 但 它 的 作 用 是 新 建 函 数 函 数 体 里 面 的 代 并 没 有 被 行, 直 到 被 用 才 会 行, 函 数 定 是 没 有 出 的 正 如 所 期 望 的, 你 必 在 行 函 数 之 前 定 个 函 数 句, 函 数 在 第 一 次 被 用 之 前 就 定 好 4.2 将 上 面 程 序 的 最 后 一 行 到 最 开 始, 函 数 用 就 出 在 函 数 定 之 前 行 程 序 并 察 出 信 息 4.3 将 函 数 回 底 部, 将 函 数 print_lyrics 定 放 在 函 数 repeat_lyrics 后 面, 会 生 什 么 果? 4.8 行 流 程 了 保 函 数 定 是 在 第 一 次 使 用 之 前, 你 就 必 知 道 句 的 行 序, 称 行 流 程 程 序 一 般 从 第 一 条 句 开 始 行, 从 上 到 下 依 次 序 行 函 数 定 并 不 改 程 序 的 行 序, 但 要 住, 函 数 只 有 被 用 的 才 会 被 行 函 数 用 像 是 是 行 流 程 中 的 一 个 迂 回 当 遇 到 要 用 的 函 数, 不 会 接 着 去 行 下 一 句, 而 是 跳 到 函 数 体, 行 完 函 数 体 里 的 句, 然 后 回 到 才 跳 出 的 地 方 行 当 你 掌 握 了 函 数 之 的 用, 就 会 得 很 在 一 个 函 数 中, 程 序 可 能 需 要 行 一 个 函 数 的 句 有, 在 定 新 函 函 数 40

数, 程 序 可 能 需 要 行 一 个 函 数! 程 序 里 跳 来 跳 去, 明 了 什 么? 程 序 有 候 没 必 要 从 看 到 尾 有 候 按 照 行 流 程 会 你 更 好 地 程 序 4.9 形 式 参 数 与 参 数 我 之 前 到 的 内 置 函 数 需 要 入 参 数 例 如, 用 math.sin 函 数 需 要 入 一 个 数 作 参 数 有 些 函 数 不 止 有 一 个 参 数 : math.pow 函 数 需 要 入 个 参 数 : 底 数 和 指 数 在 函 数 内 部, 如 果 量 作 参 数 入, 那 么 种 参 数 叫 做 形 式 参 数 ( 称 形 参 ) 下 面 的 例 子 是 一 个 自 定 函 数 入 了 一 个 参 数 ( 称 参 ): def print_twice(bruce): print bruce print bruce 个 函 数 将 一 个 叫 做 bruce 的 参 去 当 函 数 被 用, 函 数 会 打 印 次 入 的 参 数 个 函 数 适 用 任 何 型 的 >>> print_twice('spam') Spam Spam >>> print_twice(17) 17 17 >>> print_twice(math.pi) 3.14159265359 3.14159265359 种 参 数 入 方 式 适 用 于 内 置 函 数 与 自 定 函 数 任 何 型 的 表 式 都 可 以 作 函 数 print_twice 的 参 数 >>> print_twice('spam '*4) Spam Spam Spam Spam Spam Spam Spam Spam >>> print_twice(math.cos(math.pi)) -1.0-1.0 参 数 的 在 函 数 被 用 之 前 就 已 被 算 出 来 了, 因 此, 上 面 的 例 子 中 表 式 'Spam '*4 和 math.cos(math.pi) 只 被 算 了 一 次 你 可 以 使 用 量 作 参 数 : >> michael = 'Eric, the half a bee.' >>> print_twice(michael) Eric, the half a bee. Eric, the half a bee. 量 ( 如 michael) 作 形 参 与 参 ( 如 bruce) 不 同 函 数 的 形 式 参 数 是 什 么 型 的 都 可 以 被 入, 而 参 的 是 确 定 的,print_twice 函 数 的 返 回 就 是 参 数 bruce 本 身 4.10 返 回 的 函 数 和 空 函 数 函 数 41

我 使 用 的 有 些 函 数 ( 如 math 函 数 ) 有 返 回 由 于 没 有 更 好 的 叫 法, 我 称 之 有 返 回 的 函 数 其 他 的 一 些 函 数 比 如 print_twice, 行 任 但 不 返 回, 种 称 空 函 数 当 用 有 返 回 的 函 数, 大 部 分 候 你 想 要 利 用 返 回, 例 如, 将 它 一 个 量, 也 可 以 作 表 式 的 一 部 分 : x = math.cos(radians) golden = (math.sqrt(5) + 1) / 2 在 交 互 模 式 中 用 函 数,Python 会 示 果 >>> math.sqrt(5) 2.2360679774997898 在 程 序 文 件 中, 如 果 不 把 有 返 回 的 函 数 的 返 回 保 存 在 量 里 的, 返 回 就 会 失 math.sqrt(5) 空 函 数 也 会 在 屏 幕 上 出 什 么 或 者 有 其 它 的 用 途, 但 其 本 身 没 有 返 回 如 果 你 着 将 果 一 个 量, 就 会 得 到 一 个 特 殊 的 None >>> result = print_twice('bing') Bing Bing >>> print result None None 与 字 符 串 None 是 不 一 的 它 是 一 种 特 殊 的 并 且 有 自 己 的 型 >>> print type(none) <type 'NoneType'> 使 用 return 句 从 函 数 中 返 回 果 例 如, 建 一 个 的 函 数 addtwo, 将 个 数 相 加 并 且 返 回 一 个 def addtwo(a, b): added = a + b return added x = addtwo(3, 5) print x 在 文 件 中 行 程 序,print 句 会 打 印 出 8 addtwo 函 数 被 用, 入 3 和 5 个 参 数 有 形 参 a 和 b 的 函 数, 分 是 3 和 5 个 函 数 将 个 数 相 加, 然 后 将 果 局 部 量 added, 最 后 使 用 return 句 将 算 果 x 并 打 印 出 来 4.11 什 么 需 要 函 数? 如 果 不 太 明 白 什 么 需 要 花 精 力 把 程 序 分 成 多 个 函 数, 看 如 下 理 由 : 定 新 函 数 可 以 你 有 机 会 一 句 命 名, 使 得 程 序 易 于 理 解 和 函 数 可 以 消 除 冗 余 代, 程 序 瘦 身 如 果 想 修 改 函 数, 只 需 要 改 一 即 可 将 程 序 分 割 成 多 个 函 数, 逐 一, 最 后 再 整 合 在 一 起 函 数 42

精 心 的 函 数 很 多 程 序 而 言 都 会 有 用 一 旦 建 并 后, 你 就 可 以 重 复 使 用 它 本 其 余 部 分 会 使 用 函 数 定 来 解 一 个 概 念 建 并 正 确 使 用 函 数 的 技 巧 之 一 是 捕 捉 到 一 个 想 法, 例 如, 找 出 列 表 中 的 最 小 随 后 我 会 介 min 函 数 的 代, 它 将 列 表 的 作 参 数 入, 然 后 返 回 其 中 的 最 小 4.12 制 表 符 和 空 格 通 常 不 可, 致 不 易, 因 此 最 好 一 个 能 自 的 文 本 器 外, 行 程 序 之 前 不 要 忘 保 存 有 一 些 开 境 可 以 自 保 存, 而 有 一 些 不 行 未 保 存 的 情 况 下 行 的 程 序 和 文 本 器 的 程 序 不 一 如 果 你 重 复 行 相 同 的 程 序, 那 么 会 很 久 确 保 行 的 代 是 文 本 器 中 你 所 看 到 的 代 如 果 不 确 定, 你 可 以 在 程 序 开 加 入 print 'hello' 的 代 再 行 如 果 没 有 看 到 hello 出, 那 么 就 没 有 正 确 行 程 序 4.13 算 法 : 解 决 一 的 一 般 程 参 数 : 函 数 被 用 入 的 函 数 中 个 会 被 予 相 的 参 数 函 数 体 : 函 数 定 中 的 一 句 序 列 合 : 一 个 表 式 作 一 个 表 式 的 一 部 分, 或 者 一 条 句 作 一 条 句 的 一 部 分 确 定 性 : 在 既 定 入 下, 程 序 每 次 行 都 一 并 返 回 相 同 的 果 点 : 在 一 个 模 中 用 函 数, 需 要 指 定 模 名 和 函 数 名, 用 句 号 隔 开 行 流 程 : 程 序 行 的 句 行 序 返 回 的 函 数 : 能 返 回 一 个 的 函 数 函 数 : 行 一 些 有 用 操 作 的 命 名 句 序 列 函 数 不 一 定 有 参 数, 也 不 一 定 返 回 果 函 数 用 : 行 函 数 的 句, 包 括 函 数 名 和 参 数 列 表 函 数 定 : 建 新 函 数 的 句, 需 要 指 定 名 称 参 数 和 行 句 函 数 象 : 通 函 数 定 建 的 函 数 名 就 是 参 引 函 数 象 的 量 函 数 部 : 函 数 定 的 第 一 行 import 句 : 取 模 文 件 并 建 模 象 的 句 模 象 :import 句 建 的 一 个, 用 以 提 供 模 中 定 的 数 据 和 代 形 式 参 数 : 函 数 中 用 来 参 引 入 参 数 的 量 名 随 机 数 : 看 起 来 像 随 机 数 的 一 串 数, 不 是 由 确 定 的 程 序 生 的 返 回 : 函 数 的 果 如 果 一 个 函 数 用 作 表 式 来 使 用, 那 么 返 回 就 是 个 表 式 的 函 数 43

空 函 数 : 没 有 返 回 的 函 数 4.14 4.4 Python 中 def 保 留 关 字 的 作 用 是 什 么? a) 它 是 一 个 俚, 下 面 的 代 太 酷 了 b) 它 表 示 函 数 的 开 始 c) 它 表 示 接 下 来 代 的 部 分 会 被 存 d) b 和 c 都 正 确 e) 以 上 都 不 正 确 4.5 下 面 的 Python 句 会 打 印 出 什 么? def fred(): print "Zap" def jane(): print "ABC" jane() fred() jane() a) Zap ABC jane fred jane b) Zap ABC Zap c) ABC Zap jane d) ABC Zap ABC e) Zap Zap Zap 4.6 重 写 之 前 的 工 算 程 序, 加 班 的 工 按 原 工 的 150% 算 建 一 个 computepay 函 数, 包 含 个 参 数 hours 和 rate Enter Hours: 45 Enter Rate: 10 Pay: 475.0 4.7 重 写 之 前 的 分 数 算 程 序, 使 用 computegrade 函 数,score 作 参 数, 返 回 一 个 分 等 的 字 符 串 Score Grade > 0.9 A > 0.8 B > 0.7 C > 0.6 D <= 0.6 F Program Execution: 函 数 44

Enter score: 0.95 A Enter score: perfect Bad score Enter score: 10.0 Bad score Enter score: 0.75 C Enter score: 0.5 F 重 复 行 程 序, 每 次 入 不 同 的 来 出 果 函 数 45

第 5 章 迭 代 5.1 更 新 量 句 的 常 模 式 是 量 行 更 新, 量 的 新 依 于 旧 x = x+1 条 句 的 作 用 是 : 得 到 x 的 当 前, 加 一, 然 后 将 相 加 果 作 新 予 x 如 果 更 新 一 个 不 存 在 的 量, 那 么 会 出 是 因 Python 在 x 之 前, 首 先 算 等 号 右 : >>> x = x+1 NameError: name 'x' is not defined 在 更 新 量 之 前, 必 初 始 化, 通 常 使 用 的 句 : >>> x = 0 >>> x = x+1 通 加 一 操 作 更 新 量 称 增 量 更 新, 一 操 作 称 量 更 新 5.2 while 句 算 机 常 用 于 行 一 些 重 复 性 的 任 算 机 来, 行 相 同 或 相 似 的 任 而 不 出, 很, 但 人 就 做 不 好 迭 代 很 常,Python 提 供 了 一 些 功 能 句, 使 任 得 更 加 Python 的 一 种 迭 代 形 式 是 while 句 下 面 是 一 个 的 例 子, 从 5 开 始 倒 数, 然 后 打 印 出 Blastoff! n = 5 while n > 0: print n n = n-1 print 'Blastoff!' 几 乎 可 以 像 英 文 一, 条 while 句 它 的 作 用 是 : 当 n 大 于 0, 示 n 的, 然 后 n 1 当 n 等 于 0, 束 while 句, 示 blastoff! 格, while 句 的 行 流 程 如 下 : 1. 算 条 件 表 式 的, 判 断 是 True 或 False 2. 如 果 False, 束 while 句 并 行 下 一 条 句 3. 如 果 True, 行 while 中 的 句 体, 然 后 返 回 步 1 此 行 流 程 称 循 行 到 第 三 步 又 返 回 到 部 每 行 一 次 循 体, 称 一 次 迭 代 上 面 的 循, 我 可 以 它 行 了 五 次 迭 代, 表 示 循 体 被 行 了 五 次 循 体 会 改 一 个 或 多 个 量 的 因 此 当 条 件 不 足, 循 束 有 一 种 量 在 每 次 循 行 其 都 会 化, 并 控 制 迭 代 46

循 什 么 候 束, 种 量 称 迭 代 量 如 果 没 有 迭 代 量, 循 就 会 永 行 下 去, 致 无 限 循 5.3 无 限 循 于 程 序 来, 无 限 循 的 有 趣 例 就 是 洗 水 的 明, 泡 沫, 冲 洗, 重 复 就 是 一 个 无 限 循, 没 有 迭 代 量 来 表 明 什 么 候 束 个 循 上 面 的 倒 数 例 子 中, 循 的 确 是 束 了 因 n 的 个 数 是 有 限 的, 我 可 以 看 到 n 随 着 循 的 行 不 断 小, 最 0 有 些 情 况 的 循 明 是 无 限 的, 是 因 它 根 本 就 没 有 迭 代 量 5.4 无 限 循 与 break 句 有 候 循 行 到 一 半, 你 没 意 到 候 束 循 了 在 种 情 况 下, 你 可 以 写 一 个 无 限 的 循, 然 后 使 用 break 句 跳 出 循 下 面 的 代 明 是 一 个 无 限 循,while 句 的 表 式 是 常 量 True: n = 10 while True: print n, n = n - 1 print 'Done!' 如 果 犯 了 个 并 且 行 个 代, 你 会 很 快 学 会 如 何 停 止 一 个 正 在 行 的 Python 程, 或 者 找 到 算 机 的 关 机 按 由 于 循 部 的 表 式 是 常 量 True, 所 以 循 条 件 一 直 都 足, 个 程 序 会 一 直 行 下 去, 直 到 算 机 没 然 是 一 个 不 正 常 的 无 限 循, 我 是 可 以 使 用 种 模 式 来 建 立 有 用 的 循 只 要 将 break 句 放 循 体, 明 确 退 出 条 件 及 行 当 到 束 条 件, 就 可 以 束 循 例 来, 如 果 想 要 用 直 到 入 done 束 的, 代 可 以 写 : while True: line = raw_input('> ') if line == 'done': break print line print 'Done!' 个 循 的 条 件 是 True 且 不 会, 因 此 循 会 一 直 行 下 去, 直 到 触 break 句 每 次 行 个 循, 它 都 会 提 示 用 一 个 尖 括 号 如 果 用 入 done, 那 么 break 句 就 会 束 个 循 否, 个 程 序 会 一 直 提 示 用 行 入, 回 到 部 行 下 面 是 一 个 程 序 行 的 果 演 示 : > hello there hello there > finished finished > done Done! while 句 的 种 写 法 很 常 你 可 以 在 循 中 的 任 何 位 置 条 件 ( 不 局 限 于 部 ), 并 且 可 以 主 定 停 止 条 件 ( 当 生 什 么 就 停 止 ), 而 不 是 被 等 待 判 断 ( 一 直 行 直 到 生 什 么 ) 迭 代 47

5.5 使 用 continue 句 束 迭 代 有 在 循 的 迭 代 中, 你 想 要 束 当 前 迭 代, 立 刻 行 下 一 迭 代 在 种 情 况 下, 使 用 continue 句 跳 入 下 一 迭 代, 无 需 完 成 当 前 迭 代 的 循 体 下 面 的 循 例 子 不 断 打 印 入, 直 到 用 入 done 才 会 束 但 是,# 号 开 的 入 不 会 被 打 印 出 来 ( 有 点 像 Python 的 注 ) 行 一 下 个 加 入 了 continue 句 的 新 程 序 while True: line = raw_input('> ') if line[0] == '#' : continue if line == 'done': break print line print 'Done!' 除 了 # 号 开 的 行, 其 他 所 有 的 行 都 被 打 印 出 来 当 continue 句 被 行, 当 前 迭 代 会 束, 跳 到 while 句 的 开 行 下 一 循, 也 就 跳 了 print 句 5.6 使 用 for 句 定 循 有 候 我 需 要 要 遍 一 西, 例 如, 列 表, 文 件 的 每 一 行 或 是 一 数 字 遍 一 西, 可 以 用 for 句 来 造 循 因 wile 句 是 地 行 循, 直 到 条 件 False, 我 称 其 无 限 循 与 之 不 同 的 是,for 句 是 已 知 的 数 据 集 合 行 循, 因 此 它 的 迭 代 次 数 取 决 于 数 据 的 个 数 for 循 和 while 循 的 法 相 似, 下 面 是 一 个 for 句 和 循 体 代 示 例 : friends = ['Joseph', 'Glenn', 'Sally'] for friend in friends: print 'Happy New Year:', friend print 'Done!' 在 Python 法 中,friends 量 是 包 含 三 个 字 符 串 的 列 表 1 for 循 遍 整 个 列 表, 依 次 打 印 每 个 字 符 串 三 个 字 符, 出 果 如 下 所 示 : Happy New Year: Joseph Happy New Year: Glenn Happy New Year: Sally Done! 如 果 用 英 来 解 个 for 循, 就 不 如 while 循 的 解 那 么 直 接 你 可 以 把 它 当 做 一 个 朋 友 名, 那 么 段 代 的 作 用 是 : friends 集 合 中 的 每 个 朋 友 行 for 循 体 察 个 for 循,for 和 in 是 Python 的 保 留 关 字,friend 和 friends 是 量 for friend in friends: print Happy New Year, friend 具 体 来,friend 是 for 循 的 迭 代 量 量 friend 的 在 每 次 迭 代 都 会 改, 并 控 制 for 循 什 么 候 束 个 迭 代 量 取 得 friends 中 存 的 三 个 字 符 串 迭 代 48

5.7 循 模 式 我 常 使 用 for 循 或 while 循 来 遍 列 表 或 文 件 的 内 容, 会 通 来 找 一 数 中 的 最 大 或 最 小 此 循 的 造 方 法 如 下 : 循 开 始 之 前 初 始 化 一 个 或 多 个 量 在 循 体 中 每 个 数 据 行 算, 可 能 会 改 循 体 中 量 的 循 束 看 最 量 我 会 用 一 数 字 来 展 示 些 循 模 式 的 理 念 和 造 方 法 5.7.1 与 求 和 循 例 来, 了 一 个 列 表 的 数 据 个 数, for 循 写 如 下 : count = 0 for itervar in [3, 41, 12, 9, 74, 15]: count = count + 1 print 'Count: ', count 循 开 始 之 前 将 量 count 的 0, 然 后 用 一 个 for 循 来 遍 数 列 表 迭 代 量 命 名 itervar 然 我 并 不 在 循 体 中 使 用 它, 但 它 控 制 着 循, 循 体 每 一 个 列 表 行 一 次 在 循 体 中, 列 表 的 每 个 都 会 致 count 加 一 随 着 循 的 行,count 就 是 当 前 所 看 到 的 循 一 旦 束,count 就 等 于 列 表 中 数 的 个 数 在 循 最 后, 数 落 入 我 手 中 通 造 个 循, 在 循 束 我 得 到 了 想 要 的 一 个 相 似 的 循 求 出 一 数 的 和 : total = 0 for itervar in [3, 41, 12, 9, 74, 15]: total = total + itervar print 'Total: ', total 在 个 循 中, 我 用 到 了 迭 代 量 不 是 之 前 循 中 count 量 加 一, 而 是 在 每 次 循 中 加 上 的 数 字 ( 如 3 41 12 等 ) total 量 的 作 用 是 求 出 目 前 的 累 在 循 开 始 之 前, 由 于 没 有 遇 到 任 何, 所 以 total 是 0 循 中 会 累 加,total 最 是 所 有 数 字 的 和 随 着 循 的 行,total 累 了 列 表 各 的 和 的 量 有 候 被 称 累 加 器 (accumulator) 不 管 循 是 求 和 循, 在 使 用 中 都 不 是 很 有 用 是 因 Python 提 供 了 内 置 函 数 len() 和 sum(), 分 算 列 表 元 素 的 个 数 和 列 表 各 的 和 5.7.2 最 大 与 最 小 循 找 出 列 表 或 者 序 列 中 的 最 大, 造 如 下 循 : largest = None print 'Before:', largest for itervar in [3, 41, 12, 9, 74, 15]: if largest is None or itervar > largest : largest = itervar print 'Loop:', itervar, largest 迭 代 49

print 'Largest:', largest 程 序 行 果 如 下 : Before: None Loop: 3 3 Loop: 41 41 Loop: 12 41 Loop: 9 41 Loop: 74 74 Loop: 15 74 Largest: 74 largest 量 是 目 前 我 看 到 的 最 大 在 循 开 始 之 前, 将 largest 常 量 None None 是 一 个 特 殊 的 常 量, 表 示 量 空 在 循 开 始 之 前, 我 没 有 遇 到 任 何, 所 以 largest None 当 循 开 始 行, 如 果 largest None, 将 第 一 个 作 目 前 看 到 的 最 大 可 以 看 到, 第 一 迭 代 中 itervar 的 是 3,largest 的 是 None, 所 以 立 即 将 largest 的 3 第 一 次 迭 代 之 后, 最 大 就 不 是 None 了 复 合 表 式 的 第 二 部 分 置 了 触 器, itervar 是 否 大 于 largest 如 果 当 前 大 于 largest, 就 会 将 更 大 的 新 予 largest 从 程 序 出 可 以 看 出,largest 从 3 41, 然 后 74 循 束 后 遍 了 所 有 的,largest 已 是 整 个 列 表 中 的 最 大 了 算 最 小 的 代 需 要 做 很 小 改 : smallest = None print 'Before:', smallest for itervar in [3, 41, 12, 9, 74, 15]: if smallest is None or itervar < smallest: smallest = itervar print 'Loop:', itervar, smallest print 'Smallest:', smallest 同 的,smallest 在 循 前 循 中 与 循 后 都 是 目 前 看 到 的 最 小 循 束 后,smallest 就 是 整 个 列 表 的 最 小 和 求 和 同 有 Python 内 置 函 数 支 持, 比 如, 使 用 max() 函 数 和 min() 函 数 可 以 不 用 到 循 代 下 面 是 Python 内 置 函 数 min() 的 化 版 代 : def min(values): smallest = None for value in values: if smallest is None or value < smallest: smallest = value return smallest 在 段 代 中, 我 移 除 了 所 有 的 print 句, 与 Python 内 置 函 数 min() 基 本 等 价 5.8 当 程 序 越 写 越, 你 就 会 需 要 花 更 多 的 来 代 越 多 意 味 着 犯 的 机 会 越 大, 藏 的 也 就 越 多 相 反, 着 将 分 部 分 在 程 序 的 中 位 置, 找 一 可 的 代, 插 入 一 个 print 句 ( 或 者 其 它 可 效 果 的 句 ), 然 后 行 程 序 迭 代 50

如 果 中 点 出, 那 么 肯 定 出 在 程 序 的 前 半 部 分 如 果 中 点 没, 就 出 在 程 序 的 后 半 部 分 每 行 一 次 的, 你 就 会 把 代 范 一 半 如 果 代 少 于 100 行, 行 6 次 之 后, 就 只 剩 下 一 行, 理 上 至 少 是 上, 程 序 的 中 位 置 并 不 是 很 明, 也 可 能 没 法 行 行 数 然 后 除 以 2, 找 到 精 确 的 中 位 置 代 行, 种 做 法 没 有 意 一 般 做 法 是, 考 程 序 中 容 易 出 的 地 方, 行 你 极 有 可 能 会 出 的 位 置 前 后, 置 点 5.9 累 加 器 : 循 句 中 用 来 累 果 的 量 数 器 : 循 句 中 用 来 算 生 次 数 的 量 数 器 初 始 化 0, 每 次 需 要 数, 增 加 它 的 量 : 少 量 的 更 新 初 始 化 : 随 后 会 更 新 的 量 予 初 始 的 句 增 量 : 增 加 量 的 更 新 ( 通 常 是 加 一 ) 无 限 循 : 止 条 件 无 法 到 或 者 没 有 止 条 件 的 循 迭 代 : 通 函 数 用 或 者 循 来 重 复 行 一 句 5.10 5.1 写 一 个 程 序, 重 复 取 数 据, 直 到 用 入 done 一 旦 入 done, 打 印 和 个 数 与 平 均 如 果 用 入 的 不 是 数 字, 使 用 try 和 except 捕 异 常, 打 印 信 息, 然 后 跳 行 循 5.2 写 一 个 程 序, 提 示 用 入 一 数 字, 出 最 大 和 最 小, 不 要 求 平 均 1. 第 8 章 会 介 列 表 迭 代 51

第 6 章 字 符 串 6.1 字 符 串 是 字 符 的 序 列 字 符 串 是 若 干 字 符 的 序 列 你 可 以 用 方 括 号 算 符 逐 一 每 个 字 符 : >>> fruit = 'banana' >>> letter = fruit[1] 第 二 条 句 从 fruit 量 中 提 取 索 引 位 置 1 的 字 符, 并 把 它 予 letter 量 方 括 号 里 的 表 式 称 索 引 索 引 可 以 指 向 字 符 序 列 中 你 想 要 的 字 符, 作 用 如 其 名 但 是 并 不 是 你 想 要 的 果 : >>> print letter a 大 多 数 人 'banana' 的 第 一 个 字 符 是 b, 而 不 是 a 但 在 Python 中, 索 引 是 从 字 符 串 部 算 起 的 一 个 偏 移 量, 第 一 个 字 母 的 偏 移 量 0 >>> letter = fruit[0] >>> print letter b 因 此,b 是 'banana' 的 第 零 个 字 母,a 是 第 一 个 字 母,n 是 第 二 个 字 母 索 引 可 以 是 任 何 表 式, 包 括 量 与 算 符 在 内 但 是, 索 引 的 必 是 整 数, 否 会 得 到 如 下 信 息 : >>> letter = fruit[1.5] TypeError: string indices must be integers 6.2 使 用 len 函 数 得 到 字 符 串 的 度 len 是 内 置 函 数, 返 回 字 符 串 的 字 符 数 : >>> fruit = 'banana' >>> len(fruit) 6 了 得 到 字 符 串 中 的 最 后 一 个 字 母, 你 可 能 会 做 : 字 符 串 52

>>> length = len(fruit) >>> last = fruit[length] IndexError: string index out of range IndexError 的 依 据 是 字 符 串 banana 没 有 与 索 引 6 的 字 母 既 然 是 从 零 开 始 算 起, 六 个 字 母 的 号 就 是 0 到 5 了 得 到 最 后 一 个 字 母, length 1 >>> last = fruit[length-1] >>> print last a 一 种 方 法 是 使 用 索 引, 从 字 符 串 尾 倒 来 算 表 式 fruit[-1] 表 示 最 后 一 个 字 母,fruit[-2] 是 倒 数 第 二 个 字 母, 以 此 推 6.3 通 循 遍 字 符 串 按 照 一 次 一 个 字 符 的 方 式 理 一 个 字 符 串 需 要 花 大 量 的 算 通 常 从 字 符 串 部 开 始, 逐 个 每 个 字 符, 其 行 操 作, 然 后 下 一 个, 直 到 束 种 理 模 式 称 遍 (traversal) 遍 的 一 种 写 法 是 使 用 while 循 : index = 0 while index < len(fruit): letter = fruit[index] print letter index = index + 1 个 循 遍 了 整 个 字 符 串, 每 行 示 一 个 字 母 循 条 件 是 index < len(fruit), 当 index 等 于 字 符 串 度, 循 条 件 假, 那 么 句 体 就 不 会 被 行 字 符 串 最 后 一 个 字 符 的 索 引 是 len(fruit)-1 6.1 写 一 个 while 循, 从 字 符 串 的 最 后 一 个 字 符 开 始, 反 向 逐 一 理, 直 到 字 符 串 的 第 一 个 字 符, 一 行 示 一 个 字 母 遍 的 一 种 写 法 是 用 for 循 : for char in fruit: print char 每 一 次 循 中 字 符 串 的 下 一 个 字 符 char 量 循 下 去, 直 到 没 有 字 符 了 6.4 字 符 串 分 割 字 符 串 的 一 个 片 段 称 切 片, 字 符 切 片 与 字 符 的 方 法 相 似 : >>> s = 'Monty Python' >>> print s[0:5] Monty >>> print s[6:12] Python 算 符 [n:m] 返 回 字 符 串 从 第 n 到 第 m 之 的 字 符, 包 括 第 一 个 字 符, 但 不 包 括 最 后 一 个 字 符 如 果 忽 略 第 一 个 索 引 ( 冒 号 之 前 ), 切 片 就 从 字 符 串 第 一 个 字 符 开 始 算 如 果 忽 略 第 二 个 索 引, 切 片 就 算 到 最 后 一 个 字 符 串 53

字 符 : >>> fruit = 'banana' >>> fruit[:3] 'ban' >>> fruit[3:] 'ana' 如 果 第 一 个 索 引 大 于 第 二 个 索 引 致 空 字 符 串, 只 会 出 个 引 号 : >>> fruit = 'banana' >>> fruit[3:3] " 空 字 符 串 不 包 含 字 符, 其 度 0 除 此 之 外, 它 和 其 它 字 符 串 没 有 差 6.2 假 fruit 是 一 个 字 符 串, 那 么 fruit[:] 表 示 什 么? 6.5 字 符 串 是 不 可 的 在 句 的 左 使 用 [] 算 符, 改 字 符 串 中 的 字 符 例 如 下 : >>> greeting = 'Hello, world!' >>> greeting[0] = 'J' TypeError: object does not support item assignment 个 例 子 的 象 是 字 符 串, 数 据 就 是 你 想 要 的 字 符 在, 一 个 象 相 当 于 一 个, 等 下 会 修 正 个 定 数 据 是 序 列 中 的 一 个 出 原 因 在 于 字 符 串 是 不 可 改 的 意 味 着, 你 不 能 改 已 存 在 的 字 符 串 最 好 的 法 是 在 原 字 符 串 基 上 新 建 一 个 字 符 串 >>> greeting = 'Hello, world!' >>> new_greeting = 'J' + greeting[1:] >>> print new_greeting Jello, world! 个 例 子 将 新 的 首 字 母 与 greeting 的 切 片 接 在 一 起 不 会 原 先 的 字 符 串 造 成 影 6.6 循 与 下 面 的 程 序 了 字 母 a 在 字 符 串 中 出 的 次 数 : word = 'banana' count = 0 for letter in word: if letter == 'a': count = count + 1 print count 个 程 序 演 示 了 一 种 算 模 式, 称 数 器 量 count 初 始 0, 每 当 一 个 a,count 就 加 一 当 循 停 止, 字 符 串 54

count 就 得 到 了 果, 即 a 出 的 次 数 6.3 定 一 个 count 函 数 并 封 装 段 代, 其 行 通 用 化 改 造, 能 接 收 字 符 串 和 字 母 作 参 数 6.7 in 算 符 in 是 一 个 布 算 符, 个 字 符 串 行 比, 如 果 第 一 个 字 符 串 是 第 二 个 字 符 串 的 子 串, 返 回 True >>> 'a' in 'banana' True >>> 'seed' in 'banana' False 6.8 字 符 串 比 比 算 符 适 用 于 字 符 串 如 何 判 断 个 字 符 串 等 价 : if word == 'banana': print 'All right, bananas.' 其 它 比 算 符 适 用 于 字 母 排 序 : if word < 'banana': print 'Your word,' + word + ', comes before banana.' elif word > 'banana': print 'Your word,' + word + ', comes after banana.' else: print 'All right, bananas.' Python 不 能 像 人 一, 区 分 大 写 字 母 和 小 写 字 母 所 有 的 大 写 字 母 都 在 小 写 字 母 之 前, 因 此 果 如 下 : Your word, Pineapple, comes before banana. 解 决 个 的 常 方 法 是 将 字 符 串 成 一 种 准 格 式, 例 如, 在 比 之 前 都 化 小 写 6.9 字 符 串 方 法 字 符 串 是 一 种 Python 象 一 个 象 包 括 数 据 ( 即 字 符 串 本 身 ) 和 方 法 些 方 法 是 内 置 在 象 中 的 有 效 函 数, 可 以 作 用 于 象 的 任 一 例 Python 有 一 个 dir 函 数, 它 可 以 列 出 象 所 有 可 用 的 方 法 type 函 数 示 象 的 型,dir 函 数 示 的 是 象 可 用 的 方 法 >>> stuff = 'Hello world' >>> type(stuff) <type 'str'> >>> dir(stuff) ['capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 字 符 串 55

'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill'] >>> help(str.capitalize) Help on method_descriptor: capitalize(...) S.capitalize() -> string Return a copy of the string S with only its first character capitalized. >>> 当 dir 函 数 列 出 些 方 法, 你 就 可 以 用 help 取 关 于 些 方 法 的 文 档 有 关 字 符 串 方 法 比 全 面 的 文 档 http://docs.python.org/library/string.html 用 方 法 与 用 函 数 似, 都 是 入 参 数, 返 回 果, 但 它 的 法 是 不 同 的 用 方 法 的 法 是, 使 用 句 点 作 分 隔, 在 量 名 后 面 跟 上 方 法 名 例 如,upper 方 法 接 收 一 个 字 符 串, 返 回 一 个 全 部 是 大 写 字 母 的 新 字 符 串 : 次 不 使 用 upper(word) 函 数, 做 word.upper() 方 法 >>> word = 'banana' >>> new_word = word.upper() >>> print new_word BANANA 种 点 形 式 指 明 方 法 名 upper, 将 此 方 法 用 于 量 word 空 的 括 号 表 示 个 方 法 没 有 参 数 召 一 个 方 法 称 用 个 例 子 中, 在 word 象 上 用 了 upper 方 法 例 如, 字 符 串 方 法 find, 找 到 字 符 串 中 字 符 的 所 在 位 置 : >>> word = 'banana' >>> index = word.find('a') >>> print index 1 在 个 例 子 中, 我 在 word 象 上 用 find 方 法, 将 待 找 的 字 母 作 参 数 find 方 法 不 适 用 字 符, 可 以 用 于 找 子 串 : >>> word.find('na') 2 find 方 法 可 以 置 第 二 个 参 数, 从 个 索 引 位 置 开 始 找 : >>> word.find('na', 3) 4 一 个 常 任 是 利 用 strip 方 法 移 除 字 符 串 首 尾 的 空 白 ( 包 括 空 格 制 表 符 和 行 符 ) >>> line = ' Here we go ' >>> line.strip() 'Here we go' 字 符 串 56

像 startswith 的 方 法 返 回 的 是 布 >>> line = 'Please have a nice day' >>> line.startswith('please') True >>> line.startswith('p') 你 会 注 意 到,startswith 方 法 大 小 写 敏 感, 在 之 前, 使 用 lower 方 法 将 其 全 部 小 写 字 母 >>> line = 'Please have a nice day' >>> line.startswith('p') False >>> line.lower() 'please have a nice day' >>> line.lower().startswith('p') True 最 后 一 个 例 子 中 用 了 lower 方 法, 然 后 用 startswith 方 法 小 写 后 的 字 符 串 是 否 以 字 母 p 开 只 要 留 意 次 序, 我 就 可 以 在 一 个 表 式 上 用 多 种 方 法 6.4 字 符 串 方 法 count 与 之 前 的 函 数 相 似 http://docs.python.org/library/string.html, 看 个 方 法 的 文 档, 写 一 个 方 法 用, a 在 'banana' 中 出 的 次 数 6.10 字 符 串 解 析 通 常, 我 想 要 在 一 个 字 符 串 中 找 它 的 子 串 如 下 是 一 行 化 的 字 符 串 : From stephen.marquard@ uct.ac.za Sat Jan 5 09:14:16 2008 我 只 想 抽 出 子 件 的 第 二 部 分 ( 即 uct.ac.za), 可 以 通 find 方 法 和 字 符 串 切 片 来 首 先, 在 字 符 串 中 找 到 @ 符 号 的 位 置 其 次, 找 到 @ 符 号 之 后 第 一 个 空 格 所 在 的 位 置 最 后, 再 用 字 符 串 切 片 来 提 取 字 符 串 中 我 需 要 的 部 分 >>> data = 'From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008' >>> atpos = data.find('@') >>> print atpos 21 >>> sppos = data.find(' ',atpos) >>> print sppos 31 >>> host = data[atpos+1:sppos] >>> print host uct.ac.za >>> 里 使 用 的 是 find 方 法 的 一 种 用 法, 我 能 指 定 find 方 法 从 何 开 始 找 当 切 分 字 符 串, 我 提 取 的 字 符 是 位 于 @ 符 号 之 后 但 不 包 括 空 格 的 字 符 有 关 find 方 法 的 文 档, http://docs.python.org/library/string.html 6.11 格 式 操 作 符 字 符 串 57

格 式 操 作 符 % 可 以 建 字 符 串, 使 用 量 中 存 的 数 据 来 替 代 字 符 串 的 一 部 分 整 数 而 言,% 是 模 算 符 如 果 第 一 个 操 作 象 是 字 符 串, 那 么 % 就 是 格 式 操 作 符 第 一 个 操 作 象 是 格 式 字 符 串, 它 包 含 一 个 或 多 个 格 式 化 序 列, 用 来 指 定 第 二 个 操 作 象 的 格 式 最 理 果 是 字 符 串 例 如, 格 式 序 列 '%d' 表 示 第 二 个 操 作 象 会 被 格 式 化 整 数 型 (d 表 示 十 制 ): >>> camels = 42 >>> '%d' % camels '42' 行 的 果 是 字 符 串 '42', 不 要 与 整 数 42 搞 混 了 格 式 序 列 可 以 出 在 字 符 串 中 的 任 意 位 置, 所 以 你 可 以 在 一 个 句 中 嵌 入 一 个 : >>> camels = 42 >>> 'I have spotted %d camels.' % camels 'I have spotted 42 camels.' 如 果 字 符 串 中 存 在 多 个 格 式 序 列, 那 么 第 二 个 参 数 必 是 元 每 个 格 式 序 列 与 元 的 元 素 依 次 下 面 的 例 子 使 用 '%d' 格 式 化 整 数,'%g' 格 式 化 浮 点 数 ( 不 要 什 么 ),'%s' 格 式 化 字 符 串 : >>> 'In %d years I have spotted %g %s.' % (3, 0.1, 'camels') 元 中 元 素 的 数 量 必 与 字 符 串 中 的 格 式 序 列 数 量 一 致 外, 元 素 的 型 也 要 与 格 式 序 列 匹 配 : >>> '%d %d %d' % (1, 2) TypeError: not enough arguments for format string >>> '%d' % 'dollars' TypeError: illegal argument type for built-in operation 第 一 个 例 子 中 元 素 的 数 量 不, 第 二 个 例 子 中 元 素 的 格 式 是 的 格 式 算 符 很 强 大, 但 不 那 么 容 易 上 手 如 需 了 解 更 多, http://docs.python.org/lib/typesseq-strings.html 6.12 程 常 自 己, 里 可 能 出 什 么 的? 或 者 我 的 用 可 能 会 做 怎 狂 的 事 情 使 ( 看 似 ) 完 美 的 程 序 崩? 是 需 要 期 培 养 的 程 意 例 如, 第 5 章 迭 代 中 介 while 循 的 程 序 示 例 如 下 : while True: line = raw_input('> ') if line[0] == '#' : continue if line == 'done': break print line print 'Done!' 字 符 串 58

当 用 入 一 个 空 行 会 生 什 么 : > hello there hello there > # don't print this > print this! print this! > Traceback (most recent call last): File "copytildone.py", line 3, in <module> if line[0] == '#' : 入 空 行 之 前 代 行 正 常 由 于 没 有 第 0 位 字 符, 我 得 到 了 异 常 信 息 反 种 方 法 可 以 解 决 个, 即 使 一 行 空, 仍 然 能 保 安 全 行 一 种 方 法 是 使 用 startswith 方 法, 如 果 字 符 串 空 就 返 回 False 一 种 方 法 是 使 用 守 模 式, 通 一 条 if 句 行 控 制, 保 第 二 个 表 式 只 有 在 字 符 串 中 至 少 有 一 个 字 符 行 判 断 if len(line) > 0 and line[0] == '#' : 6.13 数 器 : 用 来 的 量 通 常 初 始 化 零, 然 后 累 增 空 字 符 串 : 不 包 含 字 符 度 零 的 字 符 串, 用 个 引 号 表 示 格 式 操 作 符 :% 操 作 符 格 式 字 符 串 和 元 行 操 作, 根 据 特 定 格 式 字 符 串, 元 元 素 行 格 式 化 后 生 成 一 个 字 符 串 格 式 序 列 : 格 式 字 符 串 中 的 字 符 序 列, 例 如,%d, 它 表 示 一 个 如 何 行 格 式 化 格 式 字 符 串 : 使 用 了 格 式 操 作 符 的 字 符 串, 它 包 含 了 格 式 序 列 : 用 来 表 示 条 件 是 否 真 的 布 量 用 : 方 法 的 召 句 不 可 : 序 列 的 一 种 属 性, 序 列 中 的 数 据 不 能 被 索 引 : 用 来 序 列 中 数 据 的 一 个 整 数, 例 如, 表 示 字 符 串 中 一 个 字 符 的 位 置 数 据 : 序 列 中 的 一 个 方 法 : 与 象 相 关 的 函 数, 使 用 句 点 来 用 象 : 量 可 以 引 用 的 西 在, 你 可 以 交 替 使 用 象 或 者 搜 索 : 找 到 所 要 找 的 内 容 才 会 停 止 的 一 种 遍 模 式 序 列 : 一 个 有 序 集 合, 集 合 中 的 每 个 通 一 个 整 数 索 引 定 位 切 片 : 根 据 索 引 区 指 定 字 符 串 的 一 部 分 遍 : 遍 序 列 中 的 数 据, 每 个 数 据 行 似 的 操 作 字 符 串 59

6.14 6.5 使 用 以 下 句 存 一 个 字 符 串 : str = X-DSPAM-Confidence: 0.8475 使 用 find 方 法 和 字 符 串 切 片, 提 取 出 字 符 串 中 冒 号 后 面 的 部 分, 然 后 使 用 float 函 数, 将 提 取 出 来 的 字 符 串 浮 点 数 6.6 http://docs.python.org/lib/string-methods.html, 字 符 串 方 法 的 文 档 你 可 能 想 要 拿 它 操 作 一 下, 以 便 理 解 它 的 工 作 原 理 字 符 串 方 法 中 的 strip 和 replace 特 有 用 文 档 中 使 用 的 法 可 能 会 使 人 困 惑 例 如, 在 find(sub[, start[, end]]) 中, 方 括 号 表 示 可 的 参 数 sub 是 必 需 的,start 是 可 的 ; 如 果 包 含 了 start, 那 么 end 就 是 可 的 字 符 串 60

第 7 章 文 件 7.1 持 久 性 截 止 目 前, 我 已 学 了 如 何 写 程 序, 通 条 件 行 函 数 和 迭 代 等 手 段, 与 中 央 理 器 CPU 通 我 的 意 愿 我 学 了 如 何 在 主 存 器 中 建 与 使 用 数 据 CPU 和 内 存 是 件 工 作 与 行 的 地 方 它 也 是 所 有 算 机 行 思 考 的 大 回 一 下 之 前 的 硬 件 架, 源 关 后 CPU 与 主 存 器 ( 也 就 是 内 存 ) 中 的 数 据 就 会 失 之 前 我 学 写 的 Python 程 序 作 的 本 章 介 助 存 器 ( 也 就 是 文 件 ) 源 关 后 助 存 器 里 的 数 据 不 会 借 助 U ( 存 ), 我 可 以 把 程 序 从 一 个 系 移 到 一 个 系 首 先, 我 学 文 本 文 件 的 写 里 的 文 本 文 件 是 指 我 在 文 本 器 中 建 的 然 后, 我 会 了 解 如 何 与 数 据 文 件 行 交 互, 例 如, 二 制 文 件, 通 数 据 件 行 写 7.2 打 开 文 件 从 硬 上 写 文 件 之 前, 必 首 先 打 开 个 文 件 打 开 文 件 需 要 与 操 作 系 行, 它 知 道 文 件 数 据 的 存 位 置 打 开 一 个 文 件, 操 作 系 通 文 件 名 找 到 它, 并 确 定 个 文 件 是 否 存 在 在 下 面 的 例 子 中, 我 打 开 mbox.txt 个 文 件, 它 存 在 你 行 的 python 程 序 同 一 个 文 件 下 个 示 例 用 来 打 开 mbox.txt 文 件 个 文 件 存 在 你 Python 所 在 的 那 个 文 件 从 http://www.py4inf.com/code/mbox.txt 下 个 文 件 >>> fhand = open('mbox.txt') >>> print fhand <open file 'mbox.txt', mode 'r' at 0x1005088b0> 如 果 文 件 成 功 被 打 开, 操 作 系 会 返 回 一 个 文 件 句 柄 文 件 句 柄 并 不 存 文 件 的 数 据, 只 是 一 个 操 作, 用 于 取 数 据 如 果 求 的 文 件 存 在, 你 会 得 到 一 个 句 柄 并 得 取 文 件 的 相 限 文 件 61

如 果 文 件 不 存 在, 打 开 失, 出 追 踪 信 息, 无 法 得 到 文 件 内 容 的 句 柄 >>> fhand = open('stuff.txt') Traceback (most recent call last): File "<stdin>", line 1, in <module> IOError: [Errno 2] No such file or directory: 'stuff.txt' 稍 后, 我 会 使 用 try 和 except 更 好 地 理 文 件 打 开 文 件 不 存 在 的 情 况 7.3 文 本 文 件 与 文 本 行 文 本 文 件 可 若 干 文 本 行 的 序 列, 与 Python 字 符 串 是 字 符 的 序 列 道 理 相 同 例 来, 以 下 是 一 个 文 本 文 件 示 例, 了 在 一 个 开 源 目 中 开 成 的 件 活 件 交 流 的 整 体 文 件 可 以 从 http://www.py4inf.com/code/mbox.txt 下 文 件 的 版 可 以 从 http://www.py4inf.com/code/mbox-short.txt 下 文 件 中 包 含 多 条 件, 遵 守 一 种 准 格 式 以 From 开 的 行 是 每 一 条 件 第 一 行, 以 From: 开 的 行 是 件 的 一 部 分, 注 意 区 分 更 多 信 息 http://en.wikipedia.org/wiki/mbox 将 文 本 文 件 分 解 成 文 本 行, 一 行 的 束 用 的 字 符 来 表 示, 称 行 符 Python 字 符 串 常 量 的 行 符 用 \n 表 示 看 起 来 像 个 字 符, 事 上 它 是 一 个 字 符 在 Python 解 器 中 入 量 stuff,\n 出 在 字 符 串 中, 使 用 print 句 可 以 看 到 字 符 串 被 行 符 分 成 了 行 >>> stuff = 'Hello\nWorld!' >>> stuff 'Hello\nWorld!' >>> print stuff Hello World! >>> stuff = 'X\nY' >>> print stuff X Y >>> len(stuff) 3 因 行 符 是 一 个 字 符, 所 以 字 符 串 X\nY 的 度 是 3 基 于 以 上 考, 逐 行 取 文 件, 我 需 要 知 道 每 一 行 的 尾 都 有 一 个 特 殊 的 藏 字 符, 即 行 符 之, 行 符 将 文 本 文 件 分 解 若 干 文 本 行 文 件 62

7.4 取 文 本 行 然 文 件 句 柄 并 不 包 含 文 件 的 数 据, 但 它 可 以 方 便 地 建 一 个 for 循, 按 行 依 次 取 文 件 fhand = open('mbox.txt') count = 0 for line in fhand: count = count + 1 print 'Line Count:', count python open.py Line Count: 132045 for 循 中 文 件 句 柄 被 当 做 序 列 来 使 用 在 个 示 例 中,for 循 只 是 地 算 并 出 文 件 的 行 数 个 循 大 致 用 英 可 以 翻 成 : 每 遇 到 文 件 中 的 一 行 ( 表 示 文 件 句 柄 ), 将 count 量 加 一 open 函 数 如 果 没 能 取 整 个 文 件, 可 能 是 文 件 大, 其 中 包 含 多 个 G 的 数 据 不 文 件 大 小,open 句 的 打 开 是 不 的 最,for 循 取 了 文 件 中 的 数 据 以 for 循 种 方 式 取 文 件,Python 根 据 行 符 将 文 件 数 据 分 成 若 干 文 本 行 Python 根 据 行 符 得 一 行, 每 次 迭 代 中 将 行 符 作 一 行 的 最 后 一 个 字 符 由 于 for 循 每 次 只 取 一 行 数 据, 因 此 它 能 高 效 地 取 与 出 大 型 文 件 的 文 本 行, 无 需 耗 尽 内 存 来 存 数 据 上 面 的 程 序 只 使 用 很 少 的 内 存 就 能 任 意 大 小 文 件 的 文 本 行, 它 先 取, 然 后, 最 后 舍 弃 如 果 文 件 大 小 相 于 内 存 容 量 来 很 小, 那 么 就 可 以 把 它 当 做 一 个 字 符 串, 在 文 件 句 柄 上 使 用 read 方 法 一 次 性 取 来 >>> fhand = open('mbox-short.txt') >>> inp = fhand.read() >>> print len(inp) 94626 >>> print inp[:20] From stephen.marquar 在 个 示 例 中, mbox-short.txt 整 个 文 件 ( 94626 个 字 符 ) 直 接 被 入 到 量 inp 中 我 使 用 字 符 串 分 割, 打 印 出 量 inp 中 存 的 字 符 串 前 20 个 字 符 以 种 方 式 取 文 件, 所 有 的 文 本 行 和 行 符 被 当 做 一 个 整 体, 作 一 个 大 字 符 串 存 在 inp 量 中 住, 只 有 当 算 机 内 存 能 承 文 件 数 据 大 小 的 情 况 下, 才 能 用 种 方 式 打 开 文 件 如 果 文 件 太 大, 内 容 无 法 承, 那 就 需 要 写 一 个 for 或 while 循 来 分 取 7.5 搜 索 文 件 搜 索 文 件 中 数 据 的 一 种 最 常 方 式 是 通 整 个 文 件, 只 理 符 合 特 定 条 件 的 文 本 行, 其 他 一 概 忽 略 我 将 文 件 取 与 字 符 串 方 法 合 起 来, 建 的 搜 索 机 制 例 来, 取 一 个 文 件 并 把 以 From: 开 的 行 打 印 出 来 我 可 以 使 用 字 符 串 startwith 方 法 来 符 合 前 要 求 的 行 fhand = open('mbox-short.txt') for line in fhand: if line.startswith('from:') : print line 文 件 63

程 序 行 果 如 下 : From: stephen.marquard@uct.ac.za From: louis@media.berkeley.edu From: zqian@umich.edu From: rjlowe@iupui.edu... 出 果 正 是 我 想 要 的 以 Form: 开 的 行, 但 是 什 么 会 有 多 余 的 空 行 出 呢? 是 由 于 不 可 的 行 符 所 致 每 一 行 都 以 行 符 束, 因 此 print 句 出 的 量 line 中 的 字 符 串 有 一 个 行 符,print 出 本 身 会 增 加 一 个 行 符, 所 以 最 就 成 了 空 行 我 可 以 使 用 字 符 串 分 割 来 打 印 出 不 含 最 后 一 个 字 符 的 文 本 行, 不 有 一 个 更 的 法, 使 用 rstrip 方 法 截 掉 字 符 串 后 面 的 空 白 符, 程 序 代 如 下 所 示 : fhand = open('mbox-short.txt') for line in fhand: line = line.rstrip() if line.startswith('from:') : print line 程 序 行 果 如 下 : From: stephen.marquard@uct.ac.za From: louis@media.berkeley.edu From: zqian@umich.edu From: rjlowe@iupui.edu From: zqian@umich.edu From: rjlowe@iupui.edu From: cwen@iupui.edu... 随 着 文 件 理 程 序 得 越 来 越 复, 你 可 能 会 用 到 continue 句 来 写 搜 索 循 搜 索 循 的 基 本 思 路 是 找 感 趣 的 行, 跳 不 感 趣 的 行 当 找 到 感 趣 的 的 文 本 行, 行 相 的 操 作 跳 不 感 趣 的 文 本 行 的 循, 代 如 下 所 示 : fhand = open('mbox-short.txt') for line in fhand: line = line.rstrip() # Skip 'uninteresting lines' if not line.startswith('from:') : continue # Process our 'interesting' line print line 程 序 行 果 是 一 的 可 以 理 解, 不 感 趣 的 文 本 行 就 是 那 些 不 以 From: 开 的 行, 我 使 用 continue 跳 些 行 于 感 趣 的 文 本 行, 也 就 是 那 些 以 From: 开 的 行, 我 行 相 理 我 可 以 使 用 字 符 串 方 法 find 来 模 文 本 器 的 搜 索 功 能, 找 到 任 何 一 行 中 出 待 的 字 符 串 由 于 find 方 法 可 以 找 一 个 字 符 串 在 一 个 字 符 串 中 出 的 次 数, 也 可 以 返 回 字 符 串 的 位 置 或 -1( 表 示 字 符 串 没 有 找 到 ) 我 写 一 个 循, 找 到 包 含 @uct.ac.za 字 符 串 的 文 本 行, 也 就 是 找 到 来 自 南 非 开 普 敦 大 学 的 件 fhand = open('mbox-short.txt') 文 件 64

for line in fhand: line = line.rstrip() if line.find('@uct.ac.za') == -1 : continue print line 程 序 行 果 如 下 : From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008 X-Authentication-Warning: set sender to stephen.marquard@uct.ac.za using -f From: stephen.marquard@uct.ac.za Author: stephen.marquard@uct.ac.za From david.horwitz@uct.ac.za Fri Jan 4 07:02:32 2008 X-Authentication-Warning: set sender to david.horwitz@uct.ac.za using -f From: david.horwitz@uct.ac.za Author: david.horwitz@uct.ac.za... 7.6 用 文 件 名 我 不 希 望 在 理 不 同 文 件 每 次 都 要 修 改 python 代 一 个 更 号 的 方 法 是 每 次 行 程 序, 用 自 己 入 文 件 名 一 来, 用 就 可 以 将 个 程 序 用 于 不 同 文 件, 无 需 改 Python 代 一 个 非 常 的 方 法 可 以 足 以 上 需 求, 使 用 raw_input 方 法 用 入 文 件 名, 代 如 下 所 示 : fname = raw_input('enter the file name: ') fhand = open(fname) count = 0 for line in fhand: if line.startswith('subject:') : count = count + 1 print 'There were', count, 'subject lines in', fname 从 用 那 里 得 文 件 名, 把 它 予 fname 量, 然 后 打 开 的 文 件 在, 我 可 以 不 同 的 文 件 重 复 行 个 程 序 了 python search6.py Enter the file name: mbox.txt There were 1797 subject lines in mbox.txt python search6.py Enter the file name: mbox-short.txt There were 27 subject lines in mbox-short.txt 入 下 一 小 之 前, 仔 看 段 程 序, 自 己 : 可 能 会 出 的 是 什 么? 或 者 友 好 的 用 可 能 会 做 些 什 么, 致 个 精 巧 的 程 序 会, 的 我 在 用 眼 中 就 不 那 么 酷 了 7.7 使 用 try except 与 open 告 你 不 要 看 是 最 后 的 机 会 如 果 用 入 的 不 是 一 个 文 件 名 呢? python search6.py Enter the file name: missing.txt Traceback (most recent call last): File "search6.py", line 2, in <module> 文 件 65

fhand = open(fname) IOError: [Errno 2] No such file or directory: 'missing.txt' python search6.py Enter the file name: na na boo boo Traceback (most recent call last): File "search6.py", line 2, in <module> fhand = open(fname) IOError: [Errno 2] No such file or directory: 'na na boo boo' 不 要 笑, 不 管 是 有 意 是 无 意, 用 做 的 任 何 操 作 都 有 可 能 破 坏 你 的 程 序 事 上, 件 开 中 有 一 个 重 要 的 部 分 是 量 保 障 ( 称 QA), 可 能 由 一 个 人 或 一 个 小 他 的 工 作 就 是 尽 可 能 破 坏 程 序 开 的 件 在 用 件 或 程 序 付 薪 水 之 前,QA 的 任 就 是 找 程 序 的 缺 陷 可 以,QA 是 程 序 的 最 佳 搭 档 程 序 出 可 以 用 try/except 快 速 修 复 假 open 方 法 打 开 文 件 会 出, 那 么 在 open 方 法 打 开 失, 增 加 一 个 恢 复 模 式, 代 如 下 : fname = raw_input('enter the file name: ') try: fhand = open(fname) except: print 'File cannot be opened:', fname exit() count = 0 for line in fhand: if line.startswith('subject:') : count = count + 1 print 'There were', count, 'subject lines in', fname exit 函 数 会 止 程 序, 个 程 序 永 不 返 回 当 用 ( 或 QA ) 入 不 正 确 的 文 件 名, 我 可 以 捕 它 并 快 速 行 修 复 : python search7.py Enter the file name: mbox.txt There were 1797 subject lines in mbox.txt python search7.py Enter the file name: na na boo boo File cannot be opened: na na boo boo open 方 法 用 的 保 是 Python 程 序 中 try/except 的 典 型 用 法 以 Python 方 式 做 事, 我 使 用 Pythonic 个 (Python 格 ) 上 面 的 例 子 可 称 文 件 打 开 的 Python 格 当 更 加 熟 悉 Python 后, 你 会 常 和 其 他 程 序, 个 效 果 相 同 的 方 案 一 个 更 具 有 Python 格 愈 Python 格 化 的 目 的 是 将 程 得 工 程 性 与 性 兼 我 不 要 程 序 能 正 常 工 作, 要 解 决 方 案 更 加 雅 7.8 写 入 文 件 了 能 写 入 文 件, 需 要 在 打 开 文 件 使 用 w 作 第 二 个 参 数 >>> fout = open('output.txt', 'w') >>> print fout <open file 'output.txt', mode 'w' at 0xb7eb2410> 如 果 文 件 已 存 在, 以 写 入 模 式 打 开 文 件, 会 除 旧 数 据, 因 此 慎 使 用 如 果 文 件 不 存 在, 那 么 会 建 一 个 新 的 文 件 文 件 66

文 件 句 柄 象 的 write 方 法 把 数 据 写 入 文 件 >>> line1 = 'This here's the wattle,\n' >>> fout.write(line1) 在 束 一 行, 确 保 已 明 确 插 入 了 行 符 print 句 会 自 加 上 一 个 行 符, 而 write 方 法 不 会 做 >>> line2 = 'the emblem of our land.\n' >>> fout.write(line2) 当 文 件 写 入 完 成, 得 关 文 件, 确 保 写 入 物 理 磁, 断 后 数 据 才 不 会 失 >>> fout.close() 以 方 式 打 开 文 件 也 要 得 关 文 件 只 打 开 新 文 件 就 得 有 点 粗 心 大 意 了 Python 会 在 程 序 束, 确 所 有 打 开 的 文 件 被 关 了 当 写 入 文 件, 我 要 文 件 关 行 明 确 声 明, 确 保 万 无 一 失 7.9 写 文 件, 你 可 能 会 遇 到 空 格 来 的 因 空 格 符 制 表 符 和 行 符 是 藏 的, 所 以 些 很 >>> s = '1 2\t 3\n 4' >>> print s 1 2 3 4 内 置 函 数 repr 可 以 解 决 它 将 任 一 象 作 参 数, 返 回 象 的 一 个 字 符 串 表 示 字 符 串 中 用 反 斜 杠 序 列 代 表 空 白 字 符 >>> print repr(s) '1 2\t 3\n 4' 很 有 帮 助 一 个 可 能 遇 到 的 是, 不 同 的 操 作 系 使 用 不 同 的 字 符 来 表 示 一 行 的 束 一 些 操 作 系 使 用 行 符 \n, 一 些 操 作 系 使 用 返 回 字 符 \r, 有 一 些 操 作 系 者 都 使 用 如 果 在 不 同 的 操 作 系 之 移 文 件, 些 差 异 可 能 会 致 生 大 多 数 操 作 系 都 提 供 格 式 的 用 信 息 和 更 多 疑 http://wikipedia.org/wiki/newline 当 然, 你 也 可 以 自 己 写 一 个 7.10 捕 : 使 用 try/except 句 防 止 程 序 意 外 中 止 行 符 : 在 文 件 和 字 符 串 中 表 示 一 行 尾 的 特 殊 字 符 Python 格 : Python 更 明 确 高 效 工 作 的 程 技 使 用 try 和 except 来 恢 复 失 的 文 件, 是 Python 格 的 一 个 典 型 例 文 件 67

量 保 : 件 品 整 体 量 保 的 一 个 人 或 一 个 QA 任 包 括 品 与, 一 般 在 件 布 之 前 行 文 本 文 件 : 保 存 在 永 久 存 介 ( 如 硬 ) 的 字 符 序 列 7.11 7.1 写 一 个 程 序, 取 一 个 文 件, 以 大 写 方 式 逐 行 打 印 出 文 件 内 容 程 序 行 果 如 下 所 示 : python shout.py Enter a file name: mbox-short.txt FROM STEPHEN.MARQUARD@UCT.AC.ZA SAT JAN 5 09:14:16 2008 RETURN-PATH: <POSTMASTER@COLLAB.SAKAIPROJECT.ORG> RECEIVED: FROM MURDER (MAIL.UMICH.EDU [141.211.14.90]) BY FRANKENSTEIN.MAIL.UMICH.EDU (CYRUS V2.3.8) WITH LMTPA; SAT, 05 JAN 2008 09:14:16-0500 你 可 以 从 http://www.py4inf.com/code/mbox-short.txt 下 文 本 文 件 7.2 写 一 个 程 序, 用 入 文 件 名, 然 后 取 文 件, 按 行 的 形 式 j 行 看 X-DSPAM-Confidence: 0.8475 遇 到 以 X-DSPAM-Confidence: 开 的 行, 提 取 行 中 的 浮 点 数 行 数, 算 些 行 的 件 信 度 文 件 取 束 后, 打 印 件 平 均 信 度 Enter the file name: mbox.txt Average spam confidence: 0.894128046745 Enter the file name: mbox-short.txt Average spam confidence: 0.750718518519 用 mbox.txt 和 mbox-short.txt 个 文 件 你 的 代 7.3 有 候, 程 序 感 到 无 聊 或 是 想 找 点 子, 他 会 在 程 序 里 加 入 彩 蛋 ( 无 害 的 代 ) (http://en.wikipedia.org/wiki/easter_egg_(media)) 修 改 上 面 的 程 序, 当 用 入 na na boo boo, 打 印 一 些 有 趣 的 消 息 不 管 文 件 是 否 存 在, 程 序 都 能 正 常 行 下 面 是 程 序 行 本 : python egg.py Enter the file name: mbox.txt There were 1797 subject lines in mbox.txt python egg.py Enter the file name: missing.tyxt File cannot be opened: missing.tyxt python egg.py Enter the file name: na na boo boo NA NA BOO BOO TO YOU - You have been punk'd! 不 鼓 励 你 在 程 序 里 加 入 彩 蛋, 里 只 用 作 文 件 68

第 8 章 列 表 8.1 列 表 即 序 列 与 字 符 串 似, 列 表 是 由 若 干 成 的 序 列 字 符 串 中 的 是 字 符 ; 列 表 中 的 可 以 是 任 何 型 列 表 中 的 称 元 素 或 数 据 列 表 的 建 方 法 有 好 几 种, 其 中 最 的 是 用 方 括 号 [] 将 元 素 括 起 来 : [10, 20, 30, 40] ['crunchy frog', 'ram bladder', 'lark vomit'] 第 一 个 例 子 是 由 四 个 整 数 成 的 列 表, 第 二 个 例 子 是 由 三 个 字 符 串 成 的 列 表 列 表 的 元 素 不 要 求 是 同 一 型 的 下 面 的 列 表 包 含 一 个 字 符 串, 一 个 浮 点 数, 一 个 整 数, 以 及 一 个 列 表 : ['spam', 2.0, 5, [10, 20]] 一 个 列 表 作 一 个 列 表 的 元 素 称 列 表 嵌 套 不 含 任 何 元 素 的 列 表 称 空 列 表, 使 用 空 的 方 括 号 ([]) 建 一 个 空 列 表 正 如 你 可 能 期 望 的, 可 以 把 列 表 量 : >>> cheeses = ['Cheddar', 'Edam', 'Gouda'] >>> numbers = [17, 123] >>> empty = [] >>> print cheeses, numbers, empty ['Cheddar', 'Edam', 'Gouda'] [17, 123] [] 8.2 列 表 是 可 的 列 表 元 素 的 与 字 符 串 中 字 符 的 法 是 一 的, 使 用 方 括 号 操 作 符 方 括 号 内 的 表 式 指 定 索 引 位 置 注 意, 索 引 从 0 开 始 : >>> print cheeses[0] Cheddar 与 字 符 串 不 同, 列 表 是 可 的 你 可 以 改 列 表 中 元 素 的 序, 或 者 列 表 中 的 元 素 重 新 当 括 号 算 符 出 在 句 的 左, 就 可 以 列 表 中 指 定 的 元 素 >>> numbers = [17, 123] >>> numbers[1] = 5 >>> print numbers [17, 5] numbers 列 表 的 第 二 个 元 素 之 前 是 123, 在 是 5 列 表 69

可 以 理 解, 列 表 是 索 引 与 元 素 之 的 一 种 关 系 种 关 系 称 映 射, 每 一 个 索 引 一 个 元 素 列 表 与 字 符 串 的 索 引 用 法 相 同 : 任 何 整 数 表 式 都 可 作 索 引 写 一 个 不 存 在 的 元 素, 你 会 得 到 IndexError 索 引 提 示 如 果 索 引, 表 示 从 列 表 的 尾 部 算 起 in 算 符 也 适 用 于 列 表 : >>> cheeses = ['Cheddar', 'Edam', 'Gouda'] >>> 'Edam' in cheeses True >>> 'Brie' in cheeses False 8.3 列 表 的 遍 遍 列 表 元 素 最 常 用 的 方 法 是 使 用 for 循 遍 法 与 字 符 串 遍 相 同 : for cheese in cheeses: print cheese 如 果 只 需 遍 列 表 的 元 素, 个 方 法 就 足 了 但 如 果 想 写 入 或 更 新 元 素, 就 需 要 索 引 一 个 常 方 法 是 range 函 数 和 len 函 数 的 合 使 用 : for i in range(len(numbers)): numbers[i] = numbers[i] * 2 个 循 可 以 遍 并 更 新 列 表 的 每 个 元 素 len 函 数 返 回 列 表 中 的 元 素 个 数 range 函 数 返 回 一 个 索 引 列 表 ( 取 从 0 到 n- 1), 其 中 n 是 列 表 的 度 i 行 循, 得 到 下 一 个 元 素 的 索 引 函 数 体 中 的 句 使 用 i 取 元 素 的 旧, 然 后 它 予 新 于 空 列 表 来,for 循 不 会 行 函 数 体 for x in empty: print 'This never happens.' 尽 管 一 个 列 表 可 以 包 含 一 个 列 表, 但 被 包 含 的 列 表 只 能 被 看 作 一 个 元 素 以 下 列 表 的 度 4: ['spam', 1, ['Brie', 'Roquefort', 'Pol le Veq'], [1, 2, 3]] 8.4 列 表 的 操 作 + 算 符 接 多 个 列 表 : >>> a = [1, 2, 3] >>> b = [4, 5, 6] >>> c = a + b 列 表 70

>>> print c [1, 2, 3, 4, 5, 6] 似 地, * 算 符 列 表 行 定 次 数 的 重 复 : >>> [0] * 4 [0, 0, 0, 0] >>> [1, 2, 3] * 3 [1, 2, 3, 1, 2, 3, 1, 2, 3] 第 一 个 例 子 将 列 表 [0] 重 复 了 四 次, 第 二 个 例 子 将 列 表 [1,2,3] 重 复 了 三 次 8.5 列 表 的 分 割 切 片 操 作 也 适 用 于 列 表 : >>> t = ['a', 'b', 'c', 'd', 'e', 'f'] >>> t[1:3] ['b', 'c'] >>> t[:4] ['a', 'b', 'c', 'd'] >>> t[3:] ['d', 'e', 'f'] 如 果 省 略 第 一 个 索 引, 切 片 将 从 列 表 部 开 始 ; 如 果 省 略 第 二 个 索 引, 切 片 将 理 到 列 表 的 末 尾 如 果 个 索 引 参 数 都 被 省 略, 将 会 得 到 整 个 列 表 >>> t[:] ['a', 'b', 'c', 'd', 'e', 'f'] 由 于 列 表 是 可 的, 在 行 列 表 折 拉 和 截 断 等 操 作 之 前, 最 好 保 留 一 份 列 表 的 副 本 句 左 的 切 片 操 作 可 以 更 新 多 个 元 素 : >>> t = ['a', 'b', 'c', 'd', 'e', 'f'] >>> t[1:3] = ['x', 'y'] >>> print t ['a', 'x', 'y', 'd', 'e', 'f'] 8.6 列 表 的 操 作 方 法 Python 提 供 了 一 些 操 作 列 表 方 法 例 如, 使 用 append 在 列 表 尾 部 添 加 一 个 新 元 素 >>> t = ['a', 'b', 'c'] >>> t.append('d') >>> print t ['a', 'b', 'c', 'd'] extend 可 以 将 列 表 作 参 数, 并 把 一 个 列 表 的 所 有 元 素 添 加 到 一 个 列 表 的 尾 部 >>> t1 = ['a', 'b', 'c'] 列 表 71

>>> t2 = ['d', 'e'] >>> t1.extend(t2) >>> print t1 ['a', 'b', 'c', 'd', 'e'] 个 示 例 中 t2 没 有 生 改 sort 可 以 将 列 表 元 素 从 低 到 高 排 序 >>> t = ['d', 'c', 'e', 'b', 'a'] >>> t.sort() >>> print t ['a', 'b', 'c', 'd', 'e'] 大 多 数 列 表 方 法 是 没 有 返 回 的, 它 会 修 改 列 表, 但 返 回 None 如 果 你 不 小 心 写 了 下 面 的 句 t = t.sort(), 得 到 的 t 不 是 你 所 期 的 排 序 8.7 除 元 素 除 列 表 元 素 的 方 法 有 好 几 种 如 果 知 道 元 素 的 索 引 位 置, 使 用 pop 方 法 行 除 : >>> t = ['a', 'b', 'c'] >>> x = t.pop(1) >>> print t ['a', 'c'] >>> print x b 上 面 的 程 序 使 用 pop 修 改 了 列 表, 打 印 出 了 被 除 的 元 素 如 果 没 有 指 定 索 引 位 置,pop 会 除 并 返 回 最 后 一 个 元 素 如 果 无 需 返 回 除 的 元 素, 可 以 直 接 使 用 del 操 作 符 >>> t = ['a', 'b', 'c'] >>> del t[1] >>> print t ['a', 'c'] 如 果 只 知 道 要 除 的 元 素, 但 不 知 道 它 的 索 引 位 置, 可 以 使 用 remove 方 法 : >>> t = ['a', 'b', 'c'] >>> t.remove('b') >>> print t ['a', 'c'] remove 方 法 返 回 None 当 需 要 除 多 个 元 素, 可 以 根 据 切 片 索 引, 使 用 del 来 : >>> t = ['a', 'b', 'c', 'd', 'e', 'f'] >>> del t[1:5] >>> print t ['a', 'f'] 列 表 72

一 般, 切 片 会 除 个 索 引 位 置 之 的 所 有 元 素, 上 切 片 不 会 除 第 二 个 索 引 参 数 所 的 元 素 8.8 列 表 与 函 数 列 表 有 多 内 嵌 函 数 可 用 来 遍, 无 需 写 循 代 : >>> nums = [3, 41, 12, 9, 74, 15] >>> print len(nums) 6 >>> print max(nums) 74 >>> print min(nums) 3 >>> print sum(nums) 154 >>> print sum(nums)/len(nums) 25 当 列 表 元 素 数 字,sum() 函 数 才 会 起 作 用 其 他 函 数 如 max() len() 等 字 符 串 列 表 和 其 他 可 行 比 的 数 据 型 才 会 起 作 用 我 重 写 先 前 算 数 字 列 表 平 均 的 程 序 用 入 一 个 列 表, 程 序 出 列 表 的 平 均 首 先, 不 使 用 列 表 算 平 均 的 程 序 如 下 : total = 0 count = 0 while ( True ) : inp = raw_input('enter a number: ') if inp == 'done' : break value = float(inp) total = total + value count = count + 1 average = total / count print 'Average:', average 在 个 程 序 中, 不 断 提 示 用 入 数 据, 我 使 用 count 和 sum 个 量 来 数 个 数 以 及 求 和 我 只 需 下 用 入 的 数 据, 在 循 束 后, 利 用 内 嵌 的 函 数 算 和 和 个 数 numlist = list() while ( True ) : inp = raw_input('enter a number: ') if inp == 'done' : break value = float(inp) numlist.append(value) average = sum(numlist) / len(numlist) print 'Average:', average 在 循 开 始 之 前, 首 先 建 立 一 个 空 列 表, 每 得 到 一 个 数 据, 就 把 它 添 加 到 列 表 的 尾 部 在 程 序 最 后, 只 需 将 列 表 中 数 据 的 和 除 以 列 表 的 度, 就 可 以 求 出 平 均 8.9 列 表 与 字 符 串 字 符 串 是 字 符 的 序 列, 而 列 表 是 一 系 列 的 序 列 字 符 列 表 与 字 符 串 是 不 同 的 我 可 利 用 list 方 法, 把 字 符 串 成 字 符 列 表 : 列 表 73

>>> s = 'spam' >>> t = list(s) >>> print t ['s', 'p', 'a', 'm'] 由 于 list 是 一 个 内 置 函 数, 避 免 使 用 list 作 量 名 者 也 会 避 免 使 用 l 作 量 名, 因 容 易 和 数 字 1 搞 混, 也 就 是 什 么 t 作 量 名 的 原 因 list 函 数 将 一 个 字 符 串 化 成 一 些 独 的 字 母 如 果 想 把 一 个 字 符 串 分 成 独 的, 使 用 split 函 数 : >>> s = 'pining for the fjords' >>> t = s.split() >>> print t ['pining', 'for', 'the', 'fjords'] >>> print t[2] the 一 旦 使 用 split 函 数 将 字 符 串 分 解 成 由 成 的 序 列, 你 就 可 以 利 用 索 引 操 作 符 ( 方 括 号 ) 来 列 表 中 的 特 定 了 split 函 数 有 一 个 可 参 数, 称 分 隔 符 (delimiter) 它 可 以 指 定 特 定 字 符 作 之 的 界 限 以 下 示 例 将 字 符 - 作 分 隔 符 : join 函 数 与 split 函 数 的 作 用 相 反 它 使 用 字 符 串 列 表, 把 列 表 元 素 接 起 来 join 是 字 符 串 方 法, 所 以 必 指 定 分 隔 符, 将 列 表 作 参 数 >>> t = ['pining', 'for', 'the', 'fjords'] >>> delimiter = ' ' >>> delimiter.join(t) 'pining for the fjords' 在 个 例 子 中, 分 隔 符 是 一 个 空 格 所 以 join 函 数 会 在 个 之 加 一 个 空 格 如 要 接 字 符 串 无 需 隔, 可 以 使 用 空 字 符 串 ('') 作 分 隔 符 8.10 行 解 析 From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008 split 方 法 理 此 非 常 有 效 先 写 一 个 小 程 序, 找 到 以 from 开 的 句 子, 然 后 把 些 句 子 分 解, 最 后 出 句 子 中 的 第 三 个 : fhand = open('mbox-short.txt') for line in fhand: line = line.rstrip() if not line.startswith('from ') : continue words = line.split() print words[2] 我 也 可 以 通 在 If 句 的 同 一 行 放 置 continue, 作 if 句 的 化 形 式 从 作 用 上,if 函 数 的 种 化 形 式 与 continue 在 下 一 行 的 形 式 是 一 的 程 序 行 果 如 下 : 列 表 74

Sat Fri Fri Fri... 后 章 会 介 更 复 的 行 文 本 提 取 技, 以 及 如 何 分 解 文 本 行, 从 中 找 到 我 所 需 要 的 准 确 信 息 8.11 象 与 行 以 下 句 : a = 'banana' b = 'banana' a 和 b 都 指 向 一 个 字 符 串, 但 它 所 指 向 的 是 不 是 同 一 个 字 符 串 呢? 存 在 以 下 种 情 况 : 一 种 情 况 是,a 和 b 指 向 具 有 相 同 的 个 不 同 象 一 种 情 况 是, 它 指 向 同 一 个 象 到 底 属 于 一 种 情 况, 使 用 is 算 符 ; >>> a = 'banana' >>> b = 'banana' >>> a is b True 在 个 例 子 中,Python 只 建 了 一 个 象,a 和 b 都 指 向 它 如 果 建 个 列 表 就 会 得 到 个 象 : >>> a = [1, 2, 3] >>> b = [1, 2, 3] >>> a is b False 种 情 况 下, 因 它 有 相 同 的 元 素, 我 可 以 个 列 表 是 等 价 的, 但 不 能 它 是 同 一 个 它 不 是 相 同 的 象 当 然, 如 果 个 象 是 同 一 个, 那 它 肯 定 是 等 价 的, 反 之 不 成 立 截 止 目 前, 我 在 交 替 使 用 象 和 更 的 提 法 是, 象 有 当 行 句 a = [1,2,3],a 会 指 向 一 个 列 表 象 个 列 表 象 的 是 一 个 特 定 元 素 序 列 此, 如 果 有 外 一 个 列 表 与 它 的 元 素 相 同, 那 只 能 它 有 相 同 的 8.12 名 引 用 如 果 a 指 向 一 个 象, 当 行 b=a 后, 个 量 都 将 指 向 同 一 个 象 : >>> a = [1, 2, 3] >>> b = a 列 表 75

>>> b is a True 量 与 象 之 的 关 系 称 引 用 在 个 例 子 中, 同 一 个 象 有 个 引 用 有 多 个 引 用 的 象 就 会 有 多 个 名 称, 种 象 称 作 象 被 予 了 名 如 果 名 化 的 象 是 可 的, 那 么 一 个 名 的 化, 将 会 影 到 其 他 名 的 引 用 >>> b[0] = 17 >>> print a [17, 2, 3] 尽 管 一 行 是 有 用 的, 但 也 容 易 造 成 一 般 而 言, 可 的 象 最 好 不 要 使 用 名 像 字 符 串 不 可 象 来, 名 并 不 会 造 成 很 大 如 下 所 示 : a = 'banana' b = 'banana' a 和 b 是 否 指 向 同 一 个 字 符 串, 几 乎 没 差 8.13 列 表 参 数 当 把 一 个 列 表 一 个 函 数, 函 数 就 会 得 到 列 表 的 一 个 引 用 如 果 个 函 数 改 了 一 个 列 表 参 数, 用 者 会 知 道 个 化 例 如,delete_head 除 了 列 表 的 第 一 个 元 素 : def delete_head(t): del t[0] 下 面 是 它 的 用 法 : >>> letters = ['a', 'b', 'c'] >>> delete_head(letters) >>> print letters ['b', 'c'] 上 述 参 数 t 与 量 letters 是 同 一 个 象 的 名 区 分 修 改 列 表 与 新 建 列 表 的 操 作, 是 非 常 重 要 的 例 如, 下 面 的 示 例 中,append 方 法 修 改 了 列 表, 而 + 算 符 新 建 了 一 个 列 表 : >>> t1 = [1, 2] >>> t2 = t1.append(3) >>> print t1 [1, 2, 3] >>> print t2 None >>> t3 = t1 + [3] >>> print t3 [1, 2, 3] >>> t2 is t3 False 列 表 76

在 写 列 表 的 修 改 函 数, 种 区 得 非 常 重 要 例 如, 下 面 的 函 数 就 并 没 有 到 除 列 表 元 素 的 目 的 : def bad_delete_head(t): t = t[1:] # WRONG! 切 片 操 作 会 新 建 一 个 列 表, 句 将 t 作 列 表 的 引 用 但 于 之 前 作 参 数 的 列 表 来 没 有 任 何 影 一 种 可 行 的 法 是 写 一 个 函 数, 建 并 且 返 回 一 个 新 列 表 例 如,tail 函 数 会 返 回 一 个 新 的 列 表, 其 包 含 除 第 一 个 元 素 之 外 的 其 他 所 有 元 素 def tail(t): return t[1:] 个 函 数 并 不 会 改 原 始 列 表 以 下 是 它 的 用 法 : >>> letters = ['a', 'b', 'c'] >>> rest = tail(letters) >>> print rest ['b', 'c'] 8.1 写 chop 函 数, 移 除 列 表 的 元 素 和 尾 元 素, 并 返 回 None 然 后, 写 middle 函 数, 移 除 列 表 的 元 素 和 尾 元 素, 返 回 一 个 新 列 表 8.14 列 表 及 其 他 可 象 的 不 慎 使 用, 可 能 会 造 成 的 下 面 是 一 些 常 陷 以 及 如 何 避 免 的 方 法 : 1) 大 多 数 列 表 的 方 法 会 修 改 参 数 并 返 回 None, 与 字 符 串 的 方 法 是 相 同 字 符 串 的 方 法 通 常 会 返 回 一 个 新 字 符 串, 并 不 会 改 原 始 的 字 符 串 如 果 你 如 下 的 字 符 串 代 的 写 方 式 : word = word.strip() 那 你 有 可 能 写 出 如 下 的 列 表 代 : t = t.sort() # WRONG! 因 sort 函 数 返 回 None, 所 以 接 下 来 予 量 t 会 行 失 使 用 列 表 的 方 法 和 操 作 符 之 前, 你 仔 文 档, 然 后 在 Python 的 交 互 模 式 中 列 表 与 其 他 序 列 ( 如 字 符 串 ) 共 同 有 的 方 法 和 操 作 文 档 位 于 http://docs.python.org/lib/typesseq.html 可 序 列 独 有 的 方 法 与 操 作 文 档 位 于 http://docs.python.org/lib/typesseq-mutable.html 2) 持 并 养 成 一 种 写 列 表 的 部 分 是 由 于 多 种 方 式 都 可 以 到 相 同 目 的 造 成 的 比 如, 除 列 表 元 素 的 方 法 有 pop remove del 甚 至 分 片 等 列 表 77

若 添 加 一 个 元 素, 你 也 可 以 使 用 append 方 法 或 + 算 符 不 要 忘, 下 面 的 写 法 是 正 确 的 : t.append(x) t = t + [x] 而 下 面 的 写 法 是 的 : t.append([x]) t = t.append(x) t + [x] t = t + x # WRONG! # WRONG! # WRONG! # WRONG! 在 Python 交 互 模 式 中 逐 一, 确 保 自 己 搞 清 楚 了 有, 上 面 例 子 中 只 有 最 后 一 个 会 造 成 行, 其 他 三 个 可 以 行, 只 不 没 有 按 照 我 的 期 行 3) 保 留 列 表 副 本, 避 免 直 接 引 用 如 果 使 用 像 sort 会 改 参 数 的 方 法, 要 保 留 原 始 列 表, 复 制 一 份 列 表 副 本 orig = t[:] t.sort() 在 个 例 子 中, 你 也 可 以 使 用 列 表 内 置 的 sorted 函 数 个 函 数 会 返 回 一 个 排 序 后 的 新 列 表, 而 不 会 改 原 始 列 表 在 种 情 况 下, 避 免 将 sorted 用 于 量 命 名 4) 列 表 切 片 与 文 件 当 取 和 解 析 文 件, 可 能 有 一 些 入 会 破 坏 我 的 程 序 写 一 个 程 序 来 取 文 件, 行 大 海 式 找, 打 开 守 模 式 是 很 有 必 要 的 我 重 温 之 前 的 行 取 程 序, 找 出 以 From 开 的 行 中 包 含 的 星 期 : From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008 由 于 我 将 一 行 分 解 成 了 一 个 个, 可 以 使 用 startwith 函 数, 只 需 看 每 一 行 的 第 一 个, 就 可 以 决 定 它 是 否 符 合 要 求 外, 可 以 使 用 continue 来 跳 不 是 以 From 开 的 文 本 行, 代 如 下 所 示 : fhand = open('mbox-short.txt') for line in fhand: words = line.split() if words[0]!= 'From' : continue print words[2] 看 起 来 更 了, 甚 至 都 不 需 要 行 rstrip 来 除 文 件 末 尾 的 行 符 但 就 真 得 更 好 了? python search8.py Sat Traceback (most recent call last): File "search8.py", line 5, in <module> if words[0]!= 'From' : continue IndexError: list index out of range 列 表 78

个 程 序 会 部 分 行 成 功, 我 可 以 利 地 把 第 一 个 符 合 要 求 的 行 的 第 一 个 出, 但 随 后 程 序 会 中 止, 出 一 个 追 踪 里 出 了? 到 底 是 什 么 的 混 乱 数 据, 使 得 看 似 雅 灵 活 的 Python 程 序 出? 你 也 会 真, 陷 入 深 深 的 思 考, 或 求 他 人 帮 助 最 快 捷 和 有 效 的 方 法 是, 添 加 一 个 print 句 添 加 句 的 最 佳 位 置 在 程 序 出 那 一 行 之 前, 有 可 能 打 印 出 致 出 的 数 据 然 个 方 法 会 出 大 量 的 行, 但 至 少 可 以 快 速 找 到 解 决 的 一 些 索 因 此, 我 在 第 五 句 前 面 添 加 了 一 条 打 印 量 words 的 句 我 甚 至 加 了 一 个 Debug: 前, 做 是 了 与 其 他 正 常 的 出 区 分 开 来 for line in fhand: words = line.split() print 'Debug:', words if words[0]!= 'From' : continue print words[2] 行 个 程 序, 屏 幕 会 出 大 量 式 出 在 出 的 末 尾, 我 只 需 要 看 出 和 追 踪 信 息, 便 可 知 道 在 追 踪 模 之 前 生 了 什 么 Debug: ['X-DSPAM-Confidence:', '0.8475'] Debug: ['X-DSPAM-Probability:', '0.0000'] Debug: [] Traceback (most recent call last): File "search9.py", line 6, in <module> if words[0]!= 'From' : continue IndexError: list index out of range 每 一 个 行 都 会 出 列 表, 些 是 文 本 行 行 分 解 后 得 到 的 当 程 序 出, 列 表 空 [], 在 文 本 器 中 打 开 文 件, 内 容 示 如 下 : X-DSPAM-Result: Innocent X-DSPAM-Processed: Sat Jan 5 09:14:16 2008 X-DSPAM-Confidence: 0.8475 X-DSPAM-Probability: 0.0000 Details: http://source.sakaiproject.org/viewsvn/?view=rev&rev=39772 程 序 遇 到 了 一 个 空 行, 原 来 在 里 很 然, 空 行 里 是 没 有 的 我 在 写 代 怎 么 就 没 有 考 到 个 呢? 当 程 序 着 空 行 的 第 一 个 (word[0]) 行 From 匹 配, 由 于 没 有 找 到, 所 以 就 出 索 引 范 超 出 的 在 第 五 行 添 加 守 代, 避 免 不 存 在 第 一 个 的 空 行 行 比, 个 位 置 是 最 好 的 有 多 方 法 来 守 个 代, 我 会 在 看 第 一 个 之 前, 个 数 : fhand = open('mbox-short.txt') count = 0 for line in fhand: words = line.split() # print 'Debug:', words if len(words) == 0 : continue if words[0]!= 'From' : continue print words[2] 首 先, 我 注 掉 用 于 的 print 句, 不 要 直 接 除 它 做 可 以 修 改 失 不 必 再 重 新 然 后, 我 添 加 一 个 守 句, 是 否 存 在 空, 如 果 有 的, 使 用 continue 句 跳 到 文 件 的 下 一 行 里 使 用 了 个 continue 句, 出 我 感 趣 并 希 望 理 的 文 本 行 集 合 没 有 的 行 不 是 我 想 要 的, 所 以 跳 到 下 一 行 不 是 以 From 开 的 行 也 不 符 合 要 求, 所 以 跳 列 表 79

修 改 后 的 程 序 能 成 功 行, 也 它 就 是 正 确 的 了 守 句 确 有 效 地 避 免 了 空 行, 但 那 也 不, 当 我 写 程 序 的 候, 程 我 必 常 思 考 那 里 可 能 出 了 8.2 找 出 以 上 程 序 中 一 行 仍 然 没 有 得 到 有 效 守 你 也 可 以 着 建 一 个 致 程 序 行 失 的 文 本 文 件, 然 后 修 改 程 序, 以 确 保 每 一 行 都 得 到 了 相 的 守, 确 保 程 序 能 正 确 理 你 建 的 文 本 文 件 8.3 重 写 上 例 中 的 守 句 使 用 复 合 表 式, 在 if 句 中 使 用 and 算 符 8.15 名 : 个 或 多 个 量 指 向 同 一 个 象 的 情 形 分 隔 符 : 用 来 确 定 字 符 串 如 何 被 分 割 的 字 符 或 子 字 符 串 元 素 : 列 表 ( 或 其 他 序 列 ) 中 的 一 个, 也 称 数 据 等 价 : 有 相 同 的 同 一 性 : 同 一 个 象, 可 以 推 断 出 等 价 列 表 : 一 系 列 的 序 列 列 表 遍 : 按 序 依 次 列 表 中 的 元 素 嵌 套 列 表 : 一 个 列 表 作 一 个 列 表 的 一 个 元 素 存 在 引 用 : 量 与 其 取 之 的 关 8.16 8.4 从 http://www.py4inf.com/code/romeo.txt 下 一 个 文 本 文 件 写 一 个 程 序, 打 开 romeo.txt 文 件, 按 行 取 每 一 行 使 用 split 函 数, 将 其 分 解 成 一 系 列 的 列 表 于 每 一 个, 它 是 否 已 存 在 于 列 表 之 中, 若 未 出 在 列 表 中, 把 它 添 加 来 程 序 行 束, 按 字 母 序 出 最 的 清 Enter file: romeo.txt ['Arise', 'But', 'It', 'Juliet', 'Who', 'already', 'and', 'breaks', 'east', 'envious', 'fair', 'grief', 'is', 'kill', 'light', 'moon', 'pale', 'sick', 'soft', 'sun', 'the', 'through', 'what', 'window', 'with', 'yonder'] 8.5 写 一 个 程 序, 取 箱 数 据, 当 遇 到 一 个 以 From 开 的 文 本 行, 使 用 split 函 数 将 行 子 分 解 成 我 需 要 抽 取 From 开 的 行 中 第 二 个, 即 信 人 From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008 解 析 以 From 开 的 行, 打 印 出 每 行 中 第 二 个, 可 以 信 人 数, 在 尾 出 数 下 面 是 程 序 行 果 的 部 分 出 : 列 表 80

python fromcount.py Enter a file name: mbox-short.txt stephen.marquard@uct.ac.za louis@media.berkeley.edu zqian@umich.edu [...some output removed...] ray@media.berkeley.edu cwen@iupui.edu cwen@iupui.edu cwen@iupui.edu There were 27 lines in the file with From as the first word 8.6 改 写 前 面 那 个 提 示 用 入 数 据, 并 在 用 入 done 后, 出 最 大 与 最 小 的 程 序 写 一 个 程 序, 使 用 列 表 存 用 入 的 数 据, 在 循 束 后, 利 用 max() 和 min() 函 数 分 算 出 最 大 和 最 小 Enter a number: 6 Enter a number: 2 Enter a number: 9 Enter a number: 3 Enter a number: 5 Enter a number: done Maximum: 9.0 Minimum: 2.0 列 表 81

第 9 章 字 典 字 典 很 像 列 表, 但 更 通 用 列 表 中 的 索 引 位 置 必 整 数, 而 字 典 中 索 引 几 乎 可 以 是 任 意 型 字 典 可 看 作 是 索 引 ( 里 称 ) 的 集 合 与 的 集 合 之 存 在 的 一 种 映 射 每 个 一 个, 与 之 的 关 系 称 之, 有 也 称 数 据 例 来, 我 建 一 个 英 - 西 班 牙 字 典, 其 中 与 都 是 字 符 串 dict 函 数 可 以 建 一 个 空 字 典 注 意, 由 于 dict 是 一 个 内 置 函 数 名 称, 不 能 把 它 用 作 量 名 >>> eng2sp = dict() >>> print eng2sp {} 大 括 号 {} 表 示 一 个 空 字 典 你 可 以 使 用 方 括 号 向 字 典 里 添 加 数 据 >>> eng2sp['one'] = 'uno' 行 句 建 了 一 个 从 one 到 uno 映 射 的 字 典 如 果 再 次 打 印 个 字 典, 我 会 看 到 一 个, 与 之 用 冒 号 隔 开 >>> print eng2sp {'one': 'uno'} 字 典 的 入 形 式 与 出 形 式 是 一 的 例 来, 你 可 以 建 一 个 包 含 三 个 数 据 的 字 典 : >>> eng2sp = {'one': 'uno', 'two': 'dos', 'three': 'tres'} 但 是, 如 果 你 直 接 打 印 eng2sp, 其 果 会 出 人 意 料 : >>> print eng2sp {'one': 'uno', 'three': 'tres', 'two': 'dos'} 出 的 序 生 了 改 事 上, 如 果 你 在 算 机 上 入 个 字 典, 得 到 的 出 果 跟 上 面 的 序 可 能 也 不 一 一 般 而 言, 字 典 的 序 往 往 是 不 可 的 即 便 如 此, 不 会 造 成 什 么 因 字 典 并 不 是 用 整 数 来 索 引 的, 而 是 采 用 来 找 的 >>> print eng2sp['two'] 'dos' two 的 是 dos, 与 字 典 的 序 无 关 如 果 找 的 不 在 字 典 里, 你 会 得 到 一 个 异 常 提 示 : >>> print eng2sp['four'] 字 典 82

KeyError: 'four' len 函 数 也 适 用 于 字 典, 它 会 返 回 字 典 中 的 个 数 >>> len(eng2sp) 3 in 操 作 符 也 适 用 于 字 典, 它 会 告 知 你 找 的 西 是 否 作 存 在 于 字 典 中, 但 不 能 是 否 是 作 出 很 好 的 判 断 >>> 'one' in eng2sp True >>> 'uno' in eng2sp False 了 判 断 要 找 的 西 是 否 作 存 在 于 字 典 中, 使 用 values 方 法, 它 会 返 回 字 典 中 所 有 的 一 个 列 表, 然 后 使 用 in 操 作 符 作 出 判 断 >>> vals = eng2sp.values() >>> 'uno' in vals True 列 表 与 字 典 的 in 操 作 符 算 法 上 是 有 差 的 在 列 表 中,Python 采 用 性 搜 索 策 略, 搜 索 与 列 表 度 成 正 比 在 字 典 中, Python 采 用 了 一 种 很 有 效 的 哈 希 表 算 法 种 算 法 不 管 字 典 里 面 有 多 少 数 据, 花 上 几 乎 没 有 什 么 差 此 不 述 哈 希 表 的 原 理, 更 多 相 关 知 http://wikipedia.org/wiki/hash_table 9.1 写 一 个 程 序, 取 words.txt 文 件 中 的, 将 它 作 存 在 字 典 中 此 不 需 要 关 心 的 然 后, 使 用 in 操 作 符 快 速 判 断 某 一 字 符 串 是 否 存 在 于 字 典 中 9.1 字 典 作 数 器 假 定 一 个 字 符 串, 你 想 要 知 道 其 中 每 个 字 符 出 的 次 数, 以 下 几 种 方 式 可 供 : 1. 建 26 个 量, 分 字 母 表 中 每 个 字 母 出 的 次 数 然 后, 遍 字 符 串, 每 遇 到 一 个 字 母, 相 的 数 量 加 1, 或 可 以 采 用 一 个 式 条 件 来 2. 建 一 个 包 含 26 个 元 素 的 列 表 然 后, 使 用 Python 内 置 的 ord 函 数, 将 每 一 个 字 符 成 数 字, 把 个 数 字 作 索 引 存 入 列 表, 再 增 加 相 的 数 量 3. 建 一 个 以 字 符, 其 出 次 数 作 的 字 典 首 次 遇 到 一 个 字 符, 将 其 作 一 个 数 据 添 加 到 字 典 里 之 后, 遇 到 字 典 里 已 存 在 的 数 据, 就 其 加 1 以 上 方 法 都 了 相 同 的 算 果, 但 每 种 方 法 的 算 策 略 各 不 相 同 行 算 的 一 种 方 式 称 (implementation) 有 些 方 式 于 其 他 方 式 例 来, 字 典 的 一 个 点 在 于, 我 不 必 事 先 知 道 字 符 串 中 出 了 些 字 母, 只 需 确 会 出 的 字 母 分 配 空 就 好 了 下 面 是 一 段 示 例 代 : word = 'brontosaurus' d = dict() for c in word: if c not in d: d[c] = 1 字 典 83

else: d[c] = d[c] + 1 print d 我 可 以 有 效 地 算 出 直 方 直 方 是 关 于 数 器 ( 次 ) 的 用 for 循 遍 字 符 串 每 次 循, 如 果 字 符 c 不 在 字 典 中, 我 就 建 一 个 字 典, 以 c, 初 始 1( 表 示 个 字 母 至 此 出 了 一 次 ) 如 果 c 已 存 在 于 字 典 中, 只 需 将 d[c] 加 1 即 可 程 序 行 果 如 下 : {'a': 1, 'b': 1, 'o': 2, 'n': 1, 's': 2, 'r': 2, 'u': 2, 't': 1} 直 方 表 示 字 母 a 和 b 分 出 了 一 次, c 出 了 次, 后 面 的 含 似, 不 再 述 字 典 有 一 个 get 方 法, 方 法 有 一 个 和 一 个 默 如 果 出 在 字 典 中, 那 么 它 会 返 回 此 的 如 果 不 在 字 典 中, 返 回 事 先 定 的 默 示 例 程 序 如 下 : >>> counts = { 'chuck' : 1, 'annie' : 42, 'jan': 100} >>> print counts.get('jan', 0) 100 >>> print counts.get('tim', 0) 0 我 使 用 get 方 法 可 以 把 直 方 循 写 得 更 因 get 方 法 自 理 了 不 在 字 典 中 的 情 况 的, 代 的 4 条 句 可 至 1 条, 可 以 去 掉 if 句 word = 'brontosaurus' d = dict() for c in word: d[c] = d.get(c,0) + 1 print d 使 用 get 方 法 化 数 循 的 做 法 已 成 Python 中 的 一 种 普 遍 做 法, 本 后 章 会 多 次 用 到 因 此, 你 仔 体 会 一 下,if 条 件 和 in 操 作 的 循 与 get 方 法 的 循 之 的 区 者 可 以 同 的 目 的, 但 是 后 者 更 加 9.2 字 典 与 文 件 字 典 的 常 用 法 之 一 是 面 文 字 的 文 本 文 件 行 首 先, 我 从 密 欧 与 朱 叶 中 抽 取 一 段 的 文 本, 参 照 http://shakespeare.mit.edu/tragedy/romeoandjuliet/romeo_juliet.2.2.html 由 于 开 始 接 触, 我 使 用 不 包 含 点 符 号 的 化 后 的 短 文 本 随 后 会 介 包 含 点 符 号 的 文 本 理 方 法 But soft what light through yonder window breaks It is the east and Juliet is the sun Arise fair sun and kill the envious moon Who is already sick and pale with grief 写 一 个 Python 程 序, 取 上 述 文 件 的 每 一 行, 并 将 每 一 行 分 解 由 成 的 一 个 列 表 然 后, 遍 每 个, 使 用 字 典 来 每 个 的 出 次 数 你 可 以 看 到, 段 程 序 包 含 个 for 循, 外 部 循 用 来 取 文 件 中 每 一 行, 内 部 循 迭 代 出 行 的 每 一 个 就 是 所 字 典 84

的 嵌 套 循, 其 中 一 个 外 部 循, 一 个 内 部 循 由 于 外 部 循 每 迭 代 一 次, 内 部 循 都 会 行 它 全 部 的 迭 代 基 于 一 点, 我 内 部 循 比 外 部 循 迭 代 地 更 快 个 嵌 套 循 的 合 确 保 了 入 文 件 的 每 一 行 的 每 个 都 会 被 到 fname = raw_input('enter the file name: ') try: fhand = open(fname) except: print 'File cannot be opened:', fname exit() counts = dict() for line in fhand: words = line.split() for word in words: if word not in counts: counts[word] = 1 else: counts[word] += 1 print counts 行 程 序, 生 成 一 个 包 含 全 部 数 的 原 始 文 件, 出 没 有 排 序 的 哈 希 序 列 romeo.txt 文 件 可 在 http://www.py4inf.com/code/romeo.txt 得 python count1.py Enter the file name: romeo.txt {'and': 3, 'envious': 1, 'already': 1, 'fair': 1, 'is': 3, 'through': 1, 'pale': 1, 'yonder': 1, 'what': 1, 'sun': 2, 'Who': 1, 'But': 1, 'moon': 1, 'window': 1, 'sick': 1, 'east': 1, 'breaks': 1, 'grief': 1, 'with': 1, 'light': 1, 'It': 1, 'Arise': 1, 'kill': 1, 'the': 3, 'soft': 1, 'Juliet': 1} 通 字 典 找 到 出 最 多 的 及 其 次 数, 并 不 是 那 么 方 便 因 此, 我 需 要 增 加 一 些 Python 代, 以 便 出 更 有 用 的 信 息 9.3 循 与 字 典 如 果 在 for 句 中 把 字 典 看 做 一 个 待 循 的 序 列, 它 会 遍 字 典 中 的 每 一 个 下 面 的 循 出 每 一 个 及 其 的 : counts = { 'chuck' : 1, 'annie' : 42, 'jan': 100} for key in counts: print key, counts[key] 程 序 行 果 如 下 : jan 100 chuck 1 annie 42 再 次 强, 字 典 中 的 是 没 有 固 定 序 的 我 可 以 将 种 模 式 用 到 之 前 介 的 循 的 各 种 常 用 方 法 例 如, 如 果 想 要 找 到 字 典 中 所 有 大 于 10 的, 程 序 代 如 下 : 字 典 85

counts = { 'chuck' : 1, 'annie' : 42, 'jan': 100} for key in counts: if counts[key] > 10 : print key, counts[key] for 循 是 通 字 典 的 行 迭 代 因 此, 我 必 使 用 索 引 操 作 符 来 索 相 的 程 序 行 的 出 果 如 下 : jan 100 annie 42 我 只 看 到 了 大 于 10 的 如 果 按 照 字 母 序 出 字 典 中 的, 首 先 使 用 字 典 象 的 keys 方 法, 将 所 有 的 放 入 一 个 列 表 然 后, 个 列 表 行 排 序, 排 序 后 的 列 表 行 迭 代 依 照 字 母 序, 通 每 个 出 的 : counts = { 'chuck' : 1, 'annie' : 42, 'jan': 100} lst = counts.keys() print lst lst.sort() for key in lst: print key, counts[key] 程 序 行 的 出 果 如 下 : ['jan', 'chuck', 'annie'] annie 42 chuck 1 jan 100 首 先, 通 keys 方 法 得 到 了 包 含 的 未 排 序 的 列 表 然 后, 通 for 循 得 到 有 序 的 9.4 高 文 本 解 析 上 面 示 例 程 序 用 到 的 romeo.txt 文 件 是 我 手 除 所 有 点 符 号 之 后 得 到 的 尽 可 能 化 的 文 本 的 文 本 会 包 含 大 量 点 符 号, 如 下 所 示 : But, soft! what light through yonder window breaks? It is the east, and Juliet is the sun. Arise, fair sun, and kill the envious moon, Who is already sick and pale with grief, Python 的 split 函 数 可 以 空 格, 把 看 作 是 由 空 格 分 隔 开 来 的 元, 所 以, soft 和 soft! 会 被 不 同 的, 分 它 建 一 个 字 典 由 于 文 本 中 存 在 大 写, who 和 Who 也 是 不 同 的, 分 行 通 字 符 串 的 lower punctuation 与 translate 方 法 可 以 解 决 上 述 其 中 translate 是 最 精 的 方 法 以 下 是 translate 的 明 文 档 : string.translate(s, table[, deletechars]) 首 先, 从 s 中 除 deletechars 参 数 ( 如 果 存 在 的 ) 指 定 的 所 有 字 符, 然 后 使 用 table 参 数 来 翻 字 符 table 是 一 个 256 个 字 符 的 字 符 串, 用 来 翻 每 个 字 符, 并 按 照 序 数 行 索 引 如 果 table 是 None, 只 会 行 字 符 除 步 字 典 86

里 不 指 定 table 参 数, 用 deletechars 参 数 来 除 所 有 点 符 号 Python 甚 至 可 以 告 我, 点 符 号 包 括 些 字 符 : >>> import string >>> string.punctuation '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{ }~' 我 程 序 做 出 如 下 修 改 : import string # New Code fname = raw_input('enter the file name: ') try: fhand = open(fname) except: print 'File cannot be opened:', fname exit() counts = dict() for line in fhand: line = line.translate(none, string.punctuation) line = line.lower() words = line.split() for word in words: if word not in counts: counts[word] = 1 else: counts[word] += 1 # New Code # New Code print counts 我 使 用 translate 方 法 除 了 所 有 的 点 符 号, 并 将 每 一 行 中 的 字 母 小 写 程 序 主 体 并 未 生 改 注 意, Python2.5 及 早 期 版 本 中,translate 方 法 不 接 受 None 作 第 一 个 参 数, 因 此 使 用 下 面 的 代 来 用 方 法 : print a.translate(string.maketrans(' ',' '), string.punctuation 得 一 些 Python 的 和 像 Python 一 思 考, 不 Python 多 常 数 据 分 析 内 置 了 解 决 方 案 随 着 学 的 深 入, 通 大 量 的 示 例 代 和 技 文 档 的, 你 会 知 道 去 里 找 人 是 否 用 Python 已 解 决 了 此, 从 而 一 些 你 的 工 作 以 程 序 行 的 部 分 出 果 如 下 : Enter the file name: romeo-full.txt {'swearst': 1, 'all': 6, 'afeard': 1, 'leave': 2, 'these': 2, 'kinsmen': 2, 'what': 11, 'thinkst': 1, 'love': 24, 'cloak': 1, a': 24, 'orchard': 2, 'light': 5, 'lovers': 2, 'romeo': 40, 'maiden': 1, 'whiteupturned': 1, 'juliet': 32, 'gentleman': 1, 'it': 22, 'leans': 1, 'canst': 1, 'having': 1,...} 看 些 出 仍 然 很 事, Python 来 帮 助 我 找 到 具 体 要 找 到 的 信 息 要 做 到 一 点, 我 需 要 学 Python 的 元 在 学 元 会 使 用 个 例 子 9.5 当 需 要 理 更 大 的 数 据 集, 手 工 出 与 数 据 得 不 那 么 了 以 下 是 大 数 据 集 的 一 些 建 : 少 入 : 尽 可 能 地 少 数 据 量 的 大 小 例 如, 程 序 取 一 个 文 本 文 件, 前 十 行, 或 者 最 小 的 示 例 你 可 以 文 件 本 身, 或 者 修 改 程 序, 它 只 取 文 件 的 前 n 行 后 一 种 方 式 更 好 一 些 字 典 87

当 出, 通 不 断 地 小 n 来 确 定 的 位 置 当 找 到 并 正 后, 再 不 断 增 大 n 摘 要 与 型 : 不 要 整 个 数 据 集 行 出 和, 可 以 考 先 出 数 据 的 摘 要 例 如, 字 典 的 数 据 个 数, 或 数 字 列 表 的 数 行 的 一 个 常 原 因 是 数 据 型 不 正 确 此, 通 常 出 个 的 型 就 可 以 解 决 了 写 自 程 序 : 有 通 写 代 来 自 例 如, 需 要 算 数 字 列 表 的 平 均 数, 你 可 以 个 果 是 不 是 于 列 表 的 最 大 与 最 小 之 种 称, 它 会 出 些 果 是 完 全 不 符 合 的 一 种 是 比 种 不 同 算 的 果, 它 是 否 一 致 种 称 一 致 性 工 整 化 出 果 : 的 出 果 行 格 式 化, 有 助 于 再 次 强, 在 程 序 架 上 花 些 心 思 能 有 效 少 的 花 9.6 字 典 : 一 及 其 的 映 射 哈 希 表 :Python 字 典 的 算 法 哈 希 函 数 : 使 用 哈 希 表 来 算 字 典 中 的 位 置 的 函 数 直 方 : 一 数 器 : 行 算 的 一 种 方 法 数 据 : 的 一 种 法 : 字 典 中 的 第 一 部 分 象 : 从 到 的 映 射 关 系 表 找 : 字 典 的 一 种 操 作, 根 据 找 到 的 嵌 套 循 : 一 个 循 内 部 包 括 一 个 或 多 个 循 外 部 循 每 行 一 次, 内 部 循 会 全 部 行 一 遍 : 字 典 中 的 第 二 部 分 象 里 所 的 比 之 前 提 到 的 取 更 加 指 9.7 9.2 写 一 个 程 序, 按 照 接 收 的 星 期 件 行 分 首 先, 找 出 以 From 开 的 文 本 行, 然 后, 取 出 符 合 条 件 的 每 一 行 中 的 第 三 个, 使 用 一 个 数 器 一 周 中 每 一 天 件 被 接 收 的 次 数 在 程 序 的 末 尾, 出 字 典 的 内 容 ( 不 要 求 次 序 ) Sample Line: From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008 Sample Execution: python dow.py Enter a file name: mbox-short.txt {'Fri': 20, 'Thu': 6, 'Sat': 1} 9.3 写 一 个 程 序, 取 件 日 志, 使 用 字 典 来 建 一 个 直 方, 每 个 箱 出 的 件 数 量, 然 后 出 字 典 字 典 88

Enter file name: mbox-short.txt {'gopal.ramasammycook@gmail.com': 1, 'louis@media.berkeley.edu': 3, 'cwen@iupui.edu': 5, 'antranig@caret.cam.ac.uk': 1, 'rjlowe@iupui.edu': 2, 'gsilver@umich.edu': 3, 'david.horwitz@uct.ac.za': 4, 'wagnermr@iupui.edu': 1, 'zqian@umich.edu': 4, 'stephen.marquard@uct.ac.za': 2, 'ray@media.berkeley.edu': 1} 9.4 在 上 述 程 序 中 添 加 代, 从 文 件 中 找 出 的 件 最 多 取 完 所 有 数 据 并 且 建 立 字 典 之 后, 使 用 最 大 循 ( 5.7.2) 字 典 行 遍, 找 出 的 件 最 多, 并 出 他 的 件 数 Enter a file name: mbox-short.txt cwen@iupui.edu 5 Enter a file name: mbox.txt zqian@umich.edu 195 9.5 写 一 个 程 序, 件 送 者 的 域 名, 而 不 是 件 送 者 的 件 地 址 在 程 序 的 末 尾, 出 字 典 的 内 容 python schoolcount.py Enter a file name: mbox-short.txt {'media.berkeley.edu': 4, 'uct.ac.za': 6, 'umich.edu': 7, 'gmail.com': 1, 'caret.cam.ac.uk': 1, 'iupui.edu': 8} 字 典 89

第 10 章 元 10.1 元 是 不 可 的 元 1 是 由 若 干 成 的 一 个 序 列, 与 列 表 非 常 相 似 元 中 存 的 可 以 是 任 何 数 据 型 并 有 整 数 型 索 引 元 的 一 个 重 要 特 征 是 不 可 的 元 可 以 行 比 和 使 用 哈 希 算 法, 我 可 以 其 行 排 序, 在 Python 字 典 中, 使 用 元 作 >>> t = 'a', 'b', 'c', 'd', 'e' 元 用 括 号 括 起 来, 然 不 是 必 需 的, 但 可 以 帮 助 我 在 Python 代 中 快 速 出 些 是 元 >>> t = ('a', 'b', 'c', 'd', 'e') 建 个 元 素 的 元, 必 在 末 尾 加 一 个 逗 号 >>> t1 = ('a',) >>> type(t1) <type 'tuple'> 如 果 没 有 逗 号,Python 会 将 (' a ') 作 一 个 字 符 串 理 : >>> t2 = ('a') >>> type(t2) <type 'str'> 造 元 的 一 种 方 法 是, 使 用 内 置 函 数 tuple 如 果 不 参 数,tuple 函 数 会 建 一 个 空 元 : >>> t = tuple() >>> print t () 如 果 参 数 是 一 个 序 列 ( 字 符 串 列 表 或 元 ),tuple 函 数 的 用 果 是 生 一 个 包 含 序 列 元 素 的 元 : >>> t = tuple('lupins') >>> print t ('l', 'u', 'p', 'i', 'n', 's') 由 于 tuple 是 造 器 的 名 称, 避 免 将 其 用 作 量 名 大 部 分 的 列 表 操 作 符 也 适 用 于 元 方 括 号 索 引 一 个 元 素 : >>> t = ('a', 'b', 'c', 'd', 'e') >>> print t[0] 'a' 切 片 操 作 符 一 元 素 元 90

>>> print t[1:3] ('b', 'c') 但 是, 如 果 修 改 元 中 的 元 素, 会 得 到 一 个 : >>> t[0] = 'A' TypeError: object doesn't support item assignment 不 能 修 改 元 的 元 素, 但 可 以 用 一 个 元 替 当 前 元 : >>> t = ('A',) + t[1:] >>> print t ('A', 'b', 'c', 'd', 'e') 10.2 元 的 比 比 算 符 适 用 于 元 和 其 它 序 列,Python 从 每 个 序 列 的 第 一 个 元 素 开 始 比 如 果 它 相 等, 比 下 一 个 元 素, 以 此 推, 直 到 找 到 不 同 的 元 素 找 到 不 同 元 素 之 后, 随 后 的 元 素 就 不 再 考 了 ( 即 便 它 真 得 很 大 ) >>> (0, 1, 2) < (0, 3, 4) True >>> (0, 1, 2000000) < (0, 3, 4) True 元 中 sort 函 数 正 是 个 工 作 原 理 它 首 先 第 一 个 元 素 排 序, 如 果 第 一 个 元 素 相 同, 按 第 二 个 元 素 排 序, 以 此 推 一 特 性 使 其 有 一 种 DSU 模 式 : 修 (Decorate): 修 : 在 序 列 的 元 素 之 前 放 置 一 个 或 多 个 排 序, 排 序 (Sort): 使 用 Python 内 置 函 数 sort 行 排 序, 去 修 (Undecorate): 提 取 出 序 列 中 已 排 序 的 元 素 例 来, 有 一, 它 行 由 到 短 的 排 序 : txt = 'but soft what light in yonder window breaks' words = txt.split() t = list() for word in words: t.append((len(word), word)) t.sort(reverse=true) res = list() for length, word in t: res.append(word) print res 第 一 个 循 建 了 一 个 元, 每 个 元 包 括 及 度, 度 在 前, 在 后 sort 函 数 行 比, 首 先 比 度, 如 果 度 相 等, 比 元 中 的 第 二 个 元 素 关 字 参 数 reverse=true 指 定 sort 函 数 按 照 倒 序 排 列 元 91

第 二 个 循 遍 了 元, 建 了 一 个 按 照 度 降 序 排 列 的 列 表 五 个 按 照 反 向 字 母 序 排 序, 所 以 what 出 在 soft 之 前 程 序 出 果 如 下 : ['yonder', 'window', 'breaks', 'light', 'what', 'soft', 'but', 'in'] 当 然, 一 行 文 字 被 Python 列 表, 并 按 照 度 降 序 排 列 之 后, 它 就 失 去 了 原 有 的 歌 意 味 2 10.3 元 的 Python 言 的 一 个 独 特 句 法 特 征 是, 元 可 以 出 在 句 的 左 当 左 是 一 个 序 列, 一 次 可 以 多 个 量 在 本 例 中, 一 个 列 表 ( 序 列 ) 包 含 个 元 素 使 用 一 行 句, 将 第 一 个 元 素 和 第 二 个 元 素 分 予 量 x 和 量 y >>> m = [ 'have', 'fun' ] >>> x, y = m >>> x 'have' >>> y 'fun' >>> 不 是 魔 法,Python 会 大 致 翻 元 的 法, 如 下 所 示 : 3 >>> m = [ 'have', 'fun' ] >>> x = m[0] >>> y = m[1] >>> x 'have' >>> y 'fun' >>> 从 文 体 上 看, 在 句 左 使 用 元, 我 忽 略 了 括 号, 以 下 是 有 效 的 等 价 法 : >>> m = [ 'have', 'fun' ] >>> (x, y) = m >>> x 'have' >>> y 'fun' >>> 元 有 一 个 特 巧 妙 的 用 途, 可 以 在 一 条 句 中 交 个 量 的 : >>> a, b = b, a 条 句 都 是 元, 左 是 量 元, 右 是 表 式 元 右 的 每 个 分 予 左 的 每 个 量 右 的 所 有 表 式 在 之 前 行 左 的 量 个 数 与 右 的 个 数 必 相 同 : 元 92

>>> a, b = 1, 2, 3 ValueError: too many values to unpack 更 普 遍 的 情 况 是, 右 可 以 是 任 何 型 的 序 列, 如 字 符 串 列 表 或 元 例 如, 将 件 地 址 拆 分 成 用 名 与 域 名 的 程 序 代 如 下 : >>> addr = 'monty@python.org' >>> uname, domain = addr.split('@') split 的 返 回 是 包 含 个 元 素 的 列 表 第 一 个 元 素 是 uname, 第 二 个 元 素 是 domain >>> print uname monty >>> print domain python.org 10.4 字 典 与 元 元 有 items 方 法, 方 法 返 回 元 列 表, 每 个 元 是 一 个 4 >>> d = {'a':10, 'b':1, 'c':22} >>> t = d.items() >>> print t [('a', 10), ('c', 22), ('b', 1)] 如 果 是 字 典 的, 其 中 的 数 据 是 没 有 特 定 序 的 由 于 元 列 表 本 身 是 一 个 列 表, 元 之 可 以 行 比, 以 及 元 列 表 行 排 序 将 字 典 化 元 列 表, 可 以 根 据 字 典 行 排 序, 并 出 字 典 的 内 容 >>> d = {'a':10, 'b':1, 'c':22} >>> t = d.items() >>> t [('a', 10), ('c', 22), ('b', 1)] >>> t.sort() >>> t [('a', 10), ('b', 1), ('c', 22)] 新 的 列 表 根 据 以 字 母 升 序 排 列 10.5 通 字 典 行 多 个 将 items 方 法 元 与 for 循 合 起 来, 你 可 以 有 一 个 良 好 的 代 模 式, 使 用 循 就 可 以 遍 字 典 中 的 与 for key, val in d.items(): print val, key 个 循 中 存 在 个 迭 代 量 由 于 items 返 回 一 个 元 列 表, 量 key 和 val 通 字 典 的 行 迭 代, 而 得 到 循 中 的 每 次 迭 代 都 会 使 得 key 和 value 被 予 下 一 个 字 典 ( 仍 然 以 哈 希 序 ) 元 93

此 循 的 出 果 如 下 : 10 a 22 c 1 b 再 次 强, 是 哈 希 序, 也 就 是 没 有 特 定 序 将 种 方 法 合, 按 照 每 个 中 的 来 排 序, 出 字 典 的 内 容 要 做 到 一 点, 首 先 建 一 个 元 列 表, 其 中 每 个 元 (value, key) 通 items 方 法 得 到 (key, value) 元 列 表 此, 我 想 要 根 据 value 排 序, 而 不 是 key (value, key) 元 列 表 一 旦 生 成, 排 序 就 得 了, 按 照 反 向 次 序 列 表 排 序, 出 已 排 序 的 新 列 表 >>> d = {'a':10, 'b':1, 'c':22} >>> l = list() >>> for key, val in d.items() :... l.append( (val, key) )... >>> l [(10, 'a'), (22, 'c'), (1, 'b')] >>> l.sort(reverse=true) >>> l [(22, 'c'), (10, 'a'), (1, 'b')] >>> 建 元 列 表 要 非 常 慎, 确 保 每 个 元 的 第 一 个 元 素 是, 就 能 元 列 表 行 排 序, 得 所 需 的 字 典 内 容, 字 典 已 按 行 排 序 10.6 高 回 看 看 前 面 介 的 程 序, 文 本 取 自 密 欧 于 朱 叶 的 第 二 幕 第 二 在, 我 充 个 程 序, 出 文 本 中 出 次 数 最 多 的 前 十 个, 代 如 下 所 示 : import string fhand = open('romeo-full.txt') counts = dict() for line in fhand: line = line.translate(none, string.punctuation) line = line.lower() words = line.split() for word in words: if word not in counts: counts[word] = 1 else: counts[word] += 1 # Sort the dictionary by value lst = list() for key, val in counts.items(): lst.append( (val, key) ) lst.sort(reverse=true) for key, val in lst[:10] : print key, val 程 序 的 第 一 部 分 取 文 件, 算 出 文 档 中 每 个 出 的 次 数, 将 及 其 出 次 数 放 入 字 典 中 部 分 程 序 不 做 修 改 之 前 出 量 count 的 之 后, 程 序 就 束 了, 里 我 建 一 个 (val, key) 元 列 表, 按 照 逆 序 列 表 行 排 序 元 94

由 于 元 中 是 第 一 个 元 素, 所 以 它 被 用 于 比 如 果 多 个 元 有 相 同 的, 接 下 来 元 的 第 二 个 元 素 ( ) 因 此, 如 果 相 同, 元 将 按 照 的 字 母 序 行 排 序 在 程 序 末 尾, 我 写 了 一 个 for 循, 多 个 的 迭 代, 通 列 表 切 片 操 作 (lst[:10]), 迭 代 出 前 十 个 高 至 此, 程 序 的 出 看 上 去 符 合 我 想 要 的 分 析 果 61 i 42 and 40 romeo 34 to 34 the 32 thou 32 juliet 30 that 29 my 24 thee 事 上, 如 此 复 的 数 据 解 析 与 分 析 只 需 19 行 易 于 理 解 的 Python 代 就 解 决 了 就 是 Python 言 用 于 信 息 分 析 的 明 智 依 据 之 一 10.7 在 字 典 中 使 用 作 元 元 可 以 使 用 哈 希 算 法 排 序, 但 列 表 不 可 以 如 果 我 想 在 字 典 中 建 一 个 合, 那 么 必 使 用 元 作 假 建 一 个 号 簿, 包 含 姓 名 与 号 的 关 系, 那 么 就 会 用 到 合 若 已 定 了 量 last first 与 number, 字 典 句 如 下 : directory[last,first] = number 方 括 号 里 的 表 式 是 一 个 元 在 for 循 中 使 用 元 来 遍 个 字 典 for last, first in directory: print first, last, directory[last,first] 个 循 遍 了 directory 中 的, 里 的 是 元 它 每 个 元 的 元 素 予 量 last 和 first, 然 后 打 印 出 姓 名 与 的 号 10.8 序 列 : 字 符 串 列 表 与 元 哦, 么 多! 此 的 重 点 是 元 列 表, 但 本 章 几 乎 所 有 示 例 都 可 以 用 于 列 表 的 列 表, 元 的 元 以 及 列 表 的 元 避 免 列 多, 有 方 便 称 序 列 的 序 列 在 多 情 况 下, 不 同 型 的 序 列 ( 字 符 串 列 表 与 元 ) 之 可 以 互 使 用 既 然, 什 么 要 一 种 序 列 而 不 用 其 他 序 列? 外, 如 何 合 适 的 序 列 呢? 从 最 明 的 字 符 串 起, 由 于 字 符 串 元 素 只 能 是 字 符, 所 以 它 比 其 他 序 列 的 局 限 性 更 大 外, 字 符 串 是 不 可 改 的 如 果 需 要 在 字 符 串 中 修 改 字 符, 而 不 是 新 建 一 个 字 符 串, 那 么 可 能 需 要 使 用 字 符 列 表 列 表 比 元 更 常, 主 要 是 因 列 表 是 可 的 以 下 情 况 可 能 更 适 合 元 : 某 些 情 况 下, 例 如 return 句, 它 建 元 的 法 比 建 列 表 的 要 一 些 情 况 下, 可 能 列 表 更 合 适 元 95

如 果 使 用 序 列 作 字 典 的, 那 么 必 使 用 不 可 型, 如 元 或 字 符 串 如 果 将 序 列 作 参 数 函 数, 那 么 使 用 元 会 少 由 于 名 来 意 外 情 况 的 可 能 因 元 是 不 可 的, 所 以 没 有 sort 和 reverse 可 以 修 改 已 有 列 表 的 方 法 然 而,Python 提 供 了 内 建 函 数 sorted 与 reversed, 将 任 一 序 列 作 参 数 入, 之 后 返 回 一 个 元 素 相 同 但 次 序 不 同 的 新 序 列 10.9 列 表 字 典 与 元 通 常 被 称 数 据 本 章 中 我 到 了 复 合 数 据, 例 如, 元 列 表, 以 元 列 表 的 字 典 复 合 数 据 是 有 用 的, 但 容 易 出 形 状, 即 由 于 数 据 的 型 大 小 或 成 出 所 致, 亦 或 写 代 由 于 忘 数 据 型 致 出 例 来, 如 果 列 表 包 含 一 个 整 数, 出 一 个 不 在 列 表 里 的 其 他 整 数, 就 不 起 作 用 程 序, 如 果 遇 到 困, 可 以 以 下 四 种 方 法 : : 代, 仔, 代 是 否 按 照 你 的 意 愿 行 行 : 通 修 改 代 行, 行 不 同 版 本 的 代 通 常, 程 序 在 正 确 的 地 方 示 了 正 确 的 西, 那 么 程 序 而 易, 但 有 候 得 花 些 来 建 程 序 的 支 架 沉 思 : 花 一 些 去 思 考! 型 究 竟 是 什 么? 法 行 或? 从 消 息 或 程 序 出 中 能 得 到 什 么 信 息? 什 么 的 型 会 致 你 正 遇 到 的? 在 出 之 前, 最 后 一 次 你 做 了 什 么? 回 退 : 某 些 候 最 好 的 法 是 回 退, 撤 最 近 的 修 改, 退 回 到 程 序 可 以 正 常 工 作 和 你 能 理 解 的 状 之 后 开 始 重 建 程 新 手 有 会 陷 在 些 活 之 中, 忘 其 他 事 情 每 种 活 都 有 自 身 的 故 障 模 式 例 来, 如 果 程 序 存 在 入, 只 要 不 是 概 念 上 的 解, 代 就 可 以 解 决 如 果 不 明 白 程 序 做 了 什 么, 即 使 100 遍 也 看 不 到, 因 就 在 你 的 袋 里 行 可 以 提 供 帮 助, 特 是 一 些 小 型 的 然 而, 如 果 你 没 有 思 考 或 仔 代 就 行, 那 么 可 能 会 陷 入 一 种 随 机 游 走 程 模 式, 也 就 是 通 随 机 修 改, 直 到 程 序 正 确 行 毫 无 疑, 随 机 游 走 程 会 花 很 你 必 花 去 思 考 就 像 一 科 学 你 至 少 有 一 个 关 于 的 假 如 果 存 在 个 或 更 多 可 能, 着 考 用 去 消 除 其 中 之 一 休 息 一 下 有 助 于 思 考 与 人 交 也 一 如 果 你 向 其 他 人 ( 甚 至 是 自 己 ) 解, 有 在 完 之 前, 你 就 找 到 答 案 了 但 是, 如 果 太 多 或 修 复 的 代 于 大 和 复, 即 使 最 好 的 技 也 无 于 事 有 最 好 的 是 以 退, 程 序 行 化, 直 到 你 能 掌 控 和 理 解 的 程 度 程 新 手 往 往 不 愿 意 回 退, 因 他 无 法 忍 受 除 代 ( 即 使 它 是 的 ) 如 果 你 自 己 写 的 代 感 不, 在 除 代 之 前 复 制 一 份 到 一 个 文 件 中 之 后, 你 就 能 每 次 粘 回 来 一 小 部 分 代 找 到 度 大 的 需 要 行 沉 思 以 及 而 后 退 等 步 如 果 你 陷 入 其 中 一 种, 其 他 的 10.10 可 比 的 : 相 同 型 的 之 行 比, 包 括 大 于 小 于 或 等 于 可 行 比 的 型 可 以 放 在 列 表 中, 并 可 以 排 序 数 据 : 相 关 的 集 合, 常 形 式 有 列 表 字 典 元 等 元 96

DSU: 修 - 排 序 - 去 修 的 写, 包 括 建 元 列 表 排 序 与 抽 取 部 分 果 的 一 种 模 式 聚 集 : 装 参 数 元 的 操 作 可 哈 希 的 : 有 哈 希 函 数 的 型 不 可 型, 如 整 数 浮 点 数 和 字 符 串, 都 可 以 使 用 哈 希 函 数 ; 可 型, 如 列 表 与 字 典, 不 可 以 使 用 哈 希 函 数 散 布 : 将 序 列 参 数 列 表 的 操 作 数 据 的 形 状 : 数 据 的 型 大 小 与 成 的 概 要 例 : 包 含 一 个 元 素 的 列 表 ( 或 其 他 序 列 ) 元 : 不 可 的 元 序 列 元 : 右 是 序 列, 左 是 量 元 右 通 后, 将 其 中 的 元 素 予 左 的 量 10.11 10.1 修 改 之 前 的 程 序 : 取 与 解 析 出 以 From 开 的 行, 取 出 符 合 条 件 的 行 中 的 箱 使 用 字 典 出 每 个 人 的 件 数 当 所 有 的 数 据 取 完, 从 字 典 中 建 一 个 元 (count, email) 列 表, 然 后 列 表 行 反 向 排 序, 打 印 出 提 交 最 多 的 用 Sample Line: From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008 Enter a file name: mbox-short.txt cwen@iupui.edu 5 Enter a file name: mbox.txt zqian@umich.edu 195 10.2 出 每 条 消 息 在 一 天 中 的 小 分 布 从 以 From 开 的 行 中, 找 出 字 符 串, 根 据 冒 号 将 其 分 解 每 个 小 的 次 数 行 累, 按 行 打 印 出 数, 并 按 照 小 行 排 序, 程 序 行 果 如 下 所 示 : Sample Execution: python timeofday.py Enter a file name: mbox-short.txt 04 3 06 1 07 1 09 2 10 3 11 6 14 1 15 2 16 4 17 2 18 1 19 1 10.3 写 一 个 程 序, 取 一 个 文 件, 按 照 率 降 序 打 印 出 字 母 个 程 序 将 所 有 入 化 成 小 写, 只 字 母 a-z, 不 空 格 数 字 点 符 号 以 及 其 他 a-z 之 外 的 字 符 使 用 不 同 种 的 文 本 片 段, 察 不 同 言 之 的 差 异 将 果 与 http://wikipedia.org/wiki/letter_frequencies 上 的 表 行 比 1. 有 趣 的 事 : 元 的 命 名 取 决 于 序 列 的 度, 如 一 元 (single) 二 元 (double) 三 元 (triple,) 四 元 (quadruple) 五 元 (quintuple) 六 元 (sextuple) 七 元 (septuple) 等 元 97

2. 者 注 : 此 句 出 自 莎 士 比 的 密 欧 与 朱 叶 原 文 "But, soft! what light through yonder window breaks? ", 本 作 者 略 作 修 改, 将 through 改 in 3. Python 不 做 字 面 上 的 法 翻 如 果 你 使 用 Python 的 字 典 行 言 翻, 无 法 得 到 想 要 的 果 4. Python 3.0 中 的 用 法 有 些 差 异 元 98

第 11 章 正 表 式 至 此, 我 已 学 会 如 何 取 文 件, 找 模 式 与 提 取 感 趣 的 文 本 行 片 段 文 本 行 提 取 的 方 法, 包 括 字 符 串 方 法 ( 如 split 与 find) 列 表 与 字 符 串 切 片 等 文 本 搜 索 与 抽 取 是 常 任 Python 有 非 常 强 大 的 快 速 有 效 理 此 任 的 正 表 式 正 表 式 功 能 强 大, 比 复, 其 法 需 要 一 些 来 熟 悉, 所 以 本 并 没 有 早 提 及 正 表 式 几 乎 就 是 一 关 于 字 符 串 搜 索 与 解 析 的 小 型 程 言 事 上, 整 本 都 是 正 表 式 主 展 开 本 章 介 正 表 式 基, 有 关 正 表 式 更 多 信 息, 参 以 下 网 址 : http://en.wikipedia.org/wiki/regular_expression http://docs.python.org/library/re.html 正 表 式 在 使 用 之 前 必 先 入 到 程 序 中 正 表 式 最 的 用 法 是 search() 函 数 搜 索 函 数 的 用 法 如 下 程 序 所 示 : import re hand = open('mbox-short.txt') for line in hand: line = line.rstrip() if re.search('from:', line) : print line 打 开 文 件, 循 每 一 行, 使 用 正 表 式 的 search() 函 数, 打 印 出 包 含 字 符 串 "From:" 的 文 本 行 个 程 序 其 并 没 有 正 表 式 的 真 正 力,line.find() 函 数 可 以 更 容 易 地 相 同 的 果 正 表 式 的 强 大 之 体 于, 可 以 在 搜 索 字 符 串 中 添 加 特 定 字 符, 以 更 精 确 的 字 符 串 文 本 行 的 匹 配 控 制 通 在 正 表 式 中 添 加 特 定 字 符, 写 很 少 代 就 可 以 复 的 匹 配 与 抽 取 例 如, 正 表 式 的 ^ 符 号 匹 配 一 行 的 开 始 我 修 改 一 下 上 面 的 程 序, 匹 配 From: 开 的 文 本 行 import re hand = open('mbox-short.txt') for line in hand: line = line.rstrip() if re.search('^from:', line) : print line 好 了, 就 做 到 匹 配 From: 开 的 文 本 行 仍 然 是 一 个 非 常 的 例 子, 字 符 串 的 startswith() 函 数 同 可 以 之 所 以 解, 目 的 是 介 正 表 式 的 理 念, 包 含 特 定 行 字 符, 予 文 本 匹 配 更 多 的 控 制 11.1 正 表 式 的 字 符 匹 配 多 特 定 字 符 可 以 帮 助 我 写 非 常 强 大 的 正 表 式 最 常 用 的 特 定 字 符 是 句 点, 它 可 以 匹 配 所 有 字 符 在 下 面 的 例 子 中, 正 表 式 "F..m:" 会 匹 配 配 From: "Fxxm" F12m 或 "Fl@m" 正 表 式 的 句 点 可 以 匹 配 任 意 字 符 import re hand = open('mbox-short.txt') for line in hand: line = line.rstrip() 正 表 式 99

if re.search('^f..m:', line) : print line * 和 + 表 示 一 个 字 符 可 以 重 复 任 意 次 数, 在 造 正 表 式 合 种 能 力 特 有 用 些 特 定 字 符 用 来 代 替 个 字 符, 星 号 匹 配 零 或 多 个 字 符, 加 号 匹 配 一 个 或 多 个 字 符 一 步 少 代, 以 下 示 例 使 用 重 复 的 通 配 符 : import re hand = open('mbox-short.txt') for line in hand: line = line.rstrip() if re.search('^from:.+@', line) : print line 搜 索 字 符 串 ^From:.+@ 会 成 功 匹 配 以 From: 开, 之 后 一 个 或 多 个 字 符, 以 @ 尾 的 文 本 行 果 匹 配 如 下 所 示 : From: stephen.marquard @uct.ac.za 可 以 理 解,.+ 通 配 符 匹 配 了 冒 号 与 @ 之 的 所 有 字 符 From:.+ @ 有 候, 加 号 与 星 号 可 能 会 用 力 猛 例 如 下 面 的 字 符 串 匹 配,".+" 将 其 外 推, 直 到 最 后 一 个 @ From: stephen.marquard@uct.ac.za, csev@umich.edu, and cwen @iupui.edu 通 添 加 其 他 字 符, 星 号 和 加 号 不 要 如 此 婪 地 匹 配, 是 可 以 做 到 的 情 参 关 婪 行 的 文 档 11.2 使 用 正 表 式 抽 取 数 据 在 Python 中 抽 取 字 符 串 的 数 据, 用 到 的 是 findall() 函 数 通 正 表 式 的 匹 配, 抽 取 所 有 符 合 的 子 字 符 串 以 下 示 例 从 格 式 无 关 的 任 何 文 本 行 中 抽 取 似 子 件 地 址 的 文 本 From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008 Return-Path: <postmaster@collab.sakaiproject.org> for <source@collab.sakaiproject.org>; Received: (from apache@localhost) Author: stephen.marquard@uct.ac.za 我 不 想 每 个 文 本 行 型 写 代, 每 个 文 本 行 都 分 割 和 切 片 一 次 以 下 程 序 使 用 findall() 找 到 文 本 中 的 子 件 地 址, 从 每 一 行 抽 取 一 个 或 多 个 子 件 地 址 import re s = 'Hello from csev@umich.edu to cwen@iupui.edu about the meeting @2PM' lst = re.findall('\s+@\s+', s) print lst findall() 函 数 搜 索 第 二 个 参 数 的 字 符 串, 返 回 一 个 包 含 形 如 子 件 地 址 字 符 串 的 列 表 我 使 用 字 符 序 列 来 匹 配 非 空 字 符 (\S) 正 表 式 100

程 序 行 果 如 下 : ['csev@umich.edu', 'cwen@iupui.edu'] 解 一 下 个 正 表 式, 我 找 至 少 含 有 一 个 非 空 字 符 的 子 字 符 串, 之 后 是 @, 然 后 再 是 至 少 一 个 或 多 个 非 空 字 符 \S+ 匹 配 尽 可 能 多 个 非 空 字 符 就 是 正 表 式 中 的 婪 匹 配 正 表 式 会 匹 配 个 子 件 地 址, 但 不 会 匹 配 @2PM, 原 因 是 @ 之 前 没 有 非 空 字 符 在 程 序 中 使 用 个 正 表 式, 取 文 件 的 所 有 行, 然 后 打 印 出 所 有 似 子 件 地 址 的 果, 如 下 所 示 : import re hand = open('mbox-short.txt') for line in hand: line = line.rstrip() x = re.findall('\s+@\s+', line) if len(x) > 0 : print x 取 每 一 行, 抽 取 与 正 表 式 匹 配 的 所 有 字 符 串 由 于 findall() 返 回 的 是 列 表, 我 看 下 返 回 的 列 表 不 零, 打 印 出 来 的 每 行 至 少 包 含 一 个 子 件 地 址 mbox.txt 行 程 序, 得 到 如 下 果 : ['wagnermr@iupui.edu'] ['cwen@iupui.edu'] ['<postmaster@collab.sakaiproject.org>'] ['<200801032122.m03LMFo4005148@nakamura.uits.iupui.edu>'] ['<source@collab.sakaiproject.org>;'] ['<source@collab.sakaiproject.org>;'] ['<source@collab.sakaiproject.org>;'] ['apache@localhost]'] ['source@collab.sakaiproject.org;'] 一 些 子 地 址 的 开 或 尾 包 含 了 不 正 确 的 字 符, 如 < 或 ; 里 声 明 一 下, 需 要 以 字 母 或 数 字 开 和 尾 的 字 符 串 部 分 要 做 到 一 点, 我 使 用 正 表 式 的 一 个 功 能, 使 用 方 括 号 列 多 个 可 接 受 的 匹 配 字 符 在 某 种 意 上, \S 匹 配 的 是 非 空 字 符 的 集 合 在, 我 更 清 楚 一 些 字 符 匹 配 的 本 了 下 面 是 新 的 正 表 式 : [a-za-z0-9]\s*@\s*[a-za-z] 看 起 来 有 点 复, 你 在 明 白 正 表 式 什 么 被 称 一 的 言 了 解 一 下 个 正 表 式, 找 以 一 种 子 字 符 串, 以 小 写 字 母 大 写 字 母 或 数 字 开 [a-za-z0-9], 之 后 是 零 个 或 多 个 非 空 字 符 \S, 然 后 是 @, 再 是 零 个 或 多 个 非 空 字 符 \S, 最 后 是 一 个 大 写 或 小 写 字 母 注 意, 我 从 加 号 到 星 号, 再 到 零 个 或 多 个 非 空 字 符 [a-za-z0-9] 本 身 就 是 一 个 非 空 字 符 住, 星 号 和 加 号 直 接 作 用 于 它 左 的 个 字 符 如 果 在 程 序 中 使 用 个 正 表 式, 数 据 会 得 干 一 些 : import re hand = open('mbox-short.txt') for line in hand: line = line.rstrip() x = re.findall('[a-za-z0-9]\s*@\s*[a-za-z]', line) 正 表 式 101

if len(x) > 0 : print x... ['wagnermr@iupui.edu'] ['cwen@iupui.edu'] ['postmaster@collab.sakaiproject.org'] ['200801032122.m03LMFo4005148@nakamura.uits.iupui.edu'] ['source@collab.sakaiproject.org'] ['source@collab.sakaiproject.org'] ['source@collab.sakaiproject.org'] ['apache@localhost'] 注 意 到 source@collab.sakaiproject.org 一 行, 正 表 式 消 除 了 字 符 串 尾 ( > ) 尾 的 个 字 母 原 因 是 我 在 正 表 式 末 尾 追 加 了 [a-za-z], 要 求 正 表 式 解 析 器 找 到 的 字 符 串 必 以 字 母 尾 因 此, 当 出 sakaiproject.org>;, 它 会 止 步 于 匹 配 找 到 的 最 后 一 个 字 母, 里 g 是 最 后 一 个 符 合 要 求 的 字 符 匹 配 要 注 意 的 是, 程 序 的 果 是 一 个 Python 列 表, 每 个 字 符 串 是 一 个 元 素 11.3 将 搜 索 与 抽 取 合 如 果 我 想 要 找 到 以 X- 开 的 文 本 行, 如 下 所 示 : X-DSPAM-Confidence: 0.8475 X-DSPAM-Probability: 0.0000 我 不 需 要 文 本 行 中 的 浮 点 数, 需 要 符 合 以 上 法 的 文 本 行 数 使 用 下 面 的 正 表 式 来 挑 出 符 合 要 求 的 文 本 行 : ^X-.*: [0-9.]+ 解 一 下, 文 本 以 X- 开, 之 后 是 零 个 或 多 个 字 符.*, 然 后 是 一 个 冒 号 和 一 个 空 格 空 格 之 后 是 一 个 或 多 个 字 符, 可 以 是 一 个 数 字 (0-9) 或 一 个 句 点 [0-9.]+ 需 要 注 意 的 是, 方 括 号 中 的 句 点 匹 配 的 是 句 点 本 身, 也 就 是, 它 在 方 括 号 内 不 是 通 配 符 是 一 个 非 常 的 表 式, 我 感 趣 的 文 本 匹 配 如 下 所 示 : import re hand = open('mbox-short.txt') for line in hand: line = line.rstrip() if re.search('^x\s*: [0-9.]+', line) : print line 行 个 程 序, 的 数 据 保 留 如 下 内 容 : X-DSPAM-Confidence: 0.8475 X-DSPAM-Probability: 0.0000 X-DSPAM-Confidence: 0.6178 X-DSPAM-Probability: 0.0000 在, 我 要 解 决 抽 取 数 的, 使 用 split 方 法 然 使 用 split 很, 我 里 使 用 正 表 式 的 一 个 功 能, 搜 索 与 解 析 同 行 正 表 式 102

括 号 是 正 表 式 的 一 个 特 殊 字 符 在 正 表 式 中 添 加 括 号, 括 号 的 内 容 将 在 匹 配 被 忽 略 但 是, 在 findall() 函 数 中 括 号 表 示 的 是 匹 配 括 号 内 的 整 个 表 式 在 抽 取 与 正 表 式 匹 配 的 子 字 符 串 部 分,findall() 函 数 适 用, 修 改 之 后 的 程 序 代 如 下 : import re hand = open('mbox-short.txt') for line in hand: line = line.rstrip() x = re.findall('^x\s*: ([0-9.]+)', line) if len(x) > 0 : print x 与 search() 函 数 不 同, 我 在 正 表 式 中 添 加 括 号 来 表 示 浮 点 数, 指 明 我 只 需 要 findall() 函 数 找 出 匹 配 到 的 字 符 串 的 浮 点 数 程 序 行 果 如 下 : ['0.8475'] ['0.0000'] ['0.6178'] ['0.0000'] ['0.6961'] ['0.0000'] 数 字 仍 然 是 存 在 列 表 中, 需 要 把 字 符 串 浮 点 数 里 重 展 示 正 表 式 可 以 同 行 搜 索 与 抽 取 的 功 能 如 果 文 件 包 含 如 下 形 式 的 文 本 行, 使 用 种 方 法 的 一 个 例 子 如 下 : Details: http://source.sakaiproject.org/viewsvn/?view=rev&rev=39772 如 果 想 要 抽 取 所 有 的 修 号 ( 每 一 行 末 尾 的 整 数 ), 程 序 代 如 下 : import re hand = open('mbox-short.txt') for line in hand: line = line.rstrip() x = re.findall('^details:.*rev=([0-9]+)', line) if len(x) > 0: print x 解 一 下 个 正 表 式, 以 Details: 开, 之 后 是 任 意 字 符.*, 然 后 是 rev=, 最 后 是 零 或 多 个 数 字 我 只 需 要 文 本 行 最 后 的 整 数, 所 以 用 括 号 把 [0-9]+ 括 起 来 程 序 行 果 如 下 : ['39772'] ['39771'] ['39770'] ['39769']... 住, [0-9]+ 是 婪 的, 在 抽 取 些 数 字 之 前, 它 匹 配 尽 可 能 多 的 符 合 条 件 的 字 符 串 个 婪 行 是 得 5 位 数 字 的 原 因 所 在 正 表 式 行 了 前 后 展, 直 到 它 在 开 或 尾 遇 到 一 个 非 数 字 才 停 止 匹 配 正 表 式 103

在, 我 可 以 使 用 正 表 式 重 做 之 前 的 件 消 息 中 的 提 取 文 本 内 容 如 下 : From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008 此 抽 取 每 一 行 中 当 天 的 小 之 前 的 做 法 是 用 split 次 第 一 次, 文 本 行 分 解, 取 出 第 五 个, 将 其 再 次 用 冒 号 分 解 最 后, 取 出 我 需 要 的 前 个 字 符 然 做 到 了 目, 但 在 代 写 缺 乏 一 定 灵 活 性, 前 提 是 文 本 需 要 良 好 的 格 式 化 如 果 增 加 足 的 或 一 大 的 try/except 代, 确 保 程 序 在 遇 到 格 式 不 正 确 的 文 本 行 不 会 出, 代 会 增 到 10-15 行, 那 就 不 太 好 了 使 用 下 面 的 正 表 式 可 以 更 容 易 地 做 到 一 点 : ^From.* [0-9][0-9]: 解 一 下 个 正 表 式, 以 From 开 ( 注 意 空 格 ), 之 后 是 任 意 多 个 字 符.*, 然 后 空 一 格, 接 着 是 2 位 数 字 [0-9][0-9], 最 后 是 一 个 冒 号 的 定 符 合 之 前 想 要 找 的 内 容 了 只 取 出 小 数, 使 用 findall() 方 法, 在 位 数 字 上 加 括 号, 正 表 式 如 下 : ^From.* ([0-9][0-9]): 程 序 代 如 下 : import re hand = open('mbox-short.txt') for line in hand: line = line.rstrip() x = re.findall('^from.* ([0-9][0-9]):', line) if len(x) > 0 : print x 程 序 行 果 如 下 : ['09'] ['18'] ['16'] ['15']... 11.4 字 符 由 于 在 正 表 式 中 使 用 特 殊 字 符 来 匹 配 一 行 的 开 与 尾, 或 指 定 通 配 符, 那 么 需 要 一 种 方 法 来 保 些 特 殊 字 符 本 身 的 指 代 性, 例 如 匹 配 $ 与 ^ 符 号 本 身 通 在 字 符 前 使 用 反 斜 杠 作 前 可 以 松 解 决 个 例 如, 使 用 以 下 正 表 式 找 出 金 数 import re x = 'We just received $10.00 for cookies.' y = re.findall('\$[0-9.]+',x) 由 于 $ 符 号 之 前 有 一 个 反 斜 杠, 它 上 匹 配 的 是 美 元 符 号 本 身, 不 是 匹 配 一 行 的 尾, 正 表 式 的 其 他 部 分 匹 配 一 个 或 多 个 数 字 和 句 点 注 意, 方 括 号 内, 字 符 没 有 特 殊 性 因 此,[0-9.] 表 示 数 字 和 句 点 方 括 号 之 外, 句 点 是 一 个 通 配 符, 正 表 式 104

匹 配 任 意 字 符 在 方 括 号 之 内, 句 点 就 代 表 它 本 身 11.5 小 然 本 章 只 触 及 了 正 表 式 的 皮 毛, 但 我 已 正 表 式 言 有 所 了 解 包 含 特 殊 字 符 的 搜 索 字 符 串 能 按 照 意 愿, 建 正 表 式 来 定 匹 配 的 字 符 和 想 要 抽 取 的 内 容 以 下 是 一 些 特 殊 字 符 和 字 符 序 列 : ^ 匹 配 文 本 行 的 开 $ 匹 配 文 本 行 的 尾. 匹 配 任 一 字 符 ( 一 个 通 配 符 ) \s 匹 配 一 个 空 白 字 符 \S 匹 配 一 个 非 空 字 符 ( 与 \s 相 反 ) * 用 于 前 接 字 符, 表 示 前 接 字 符 的 零 个 或 多 个 匹 配 *? 用 于 前 接 字 符, 以 非 婪 模 式, 表 示 前 接 字 符 的 零 个 或 多 个 匹 配 + 用 于 前 接 字 符, 表 示 前 接 字 符 的 一 个 或 多 个 匹 配 +? 用 于 前 接 字 符, 以 非 婪 模 式, 表 示 前 接 字 符 的 一 个 或 多 个 匹 配 [aeiou] 匹 配 指 定 字 符 集 中 的 一 个 字 符 里 只 能 是 a e i o 或 u, 不 接 受 其 他 字 符 [a-z0-9] 使 用 号 指 定 字 符 区 里 表 示 一 个 字 符, 必 是 小 写 字 母 或 数 字 [^A-Za-z] 第 一 个 字 符 是 ^, 它 表 示 反 向 里 匹 配 除 了 大 小 写 字 符 之 外 的 其 他 任 意 字 符 ( ) 在 正 表 式 中 添 加 括 号, 括 号 内 容 会 失 匹 配 功 能, 但 在 findall() 中 可 以 用 于 抽 取 特 定 部 分 的 字 符 串, 而 不 是 整 个 字 符 串 \b 匹 配 空 字 符 串, 用 于 的 首 尾 \B 匹 配 空 字 符 串, 但 不 能 用 于 的 首 尾 \d 匹 配 任 意 十 制 数 字, 等 价 于 [0-9] \D 匹 配 任 意 非 数 字 字 符, 等 价 于 0-9 11.6 Unix 用 福 利 自 20 世 60 年 以 后,Unix 操 作 系 内 置 了 文 件 搜 索 的 正 表 式 功 能 它 几 乎 在 所 有 程 言 中 通 用, 只 是 上 有 所 差 事 上,Unix 内 置 了 一 个 命 令 行 工 具, 称 grep(generalized Regular Expression Parser, 通 用 正 表 式 解 析 器 ), 可 以 本 章 search() 在 示 例 中 的 相 同 作 用 如 果 使 用 Mac 或 Linux 操 作 系, 你 可 以 在 命 令 行 窗 口 中 行 以 下 句 $ grep '^From:' mbox-short.txt From: stephen.marquard@uct.ac.za From: louis@media.berkeley.edu From: zqian@umich.edu From: rjlowe@iupui.edu 正 表 式 105

![Alt text](./1434462994117.png) 条 命 令 告 grep, 示 mbox-short.txt 文 件 中 以 From: 开 的 字 符 串 如 果 使 用 grep 命 令 和 grep 的 文 档, 你 会 Python 支 持 的 正 表 式 与 grep 支 持 的 正 表 式 存 在 一 些 微 差 例 如,grep 不 支 持 非 空 字 符 \S, 所 以 需 要 使 用 稍 微 复 一 点 的 集 合 符 号 [^ ], 表 示 匹 配 非 空 格 的 任 意 字 符 11.7 Python 包 含 一 些 明 了 的 内 置 文 档, 有 助 于 快 速 掌 握 和 特 定 方 法 的 确 确 切 名 称 些 文 档 可 以 在 Python 解 析 器 的 交 互 模 式 下 看 >>> help() Welcome to Python 2.6! This is the online help utility. If this is your first time using Python, you should definitely check out the tutorial on the Internet at http://docs.python.org/tutorial/. Enter the name of any module, keyword, or topic to get help on writing Python programs and using Python modules. To quit this help utility and return to the interpreter, just type "quit". To get a list of available modules, keywords, or topics, type "modules", "keywords", or "topics". Each module also comes with a one-line summary of what it does; to list the modules whose summaries contain a given word such as "spam", type "modules spam". help> modules 如 果 你 知 道 需 要 使 用 的 模 名 称, 使 用 dir() 命 令 找 个 模 的 方 法, 如 下 所 示 : >>> import re >>> dir(re) [.. 'compile', 'copy_reg', 'error', 'escape', 'findall', 'finditer', 'match', 'purge', 'search', 'split', 'sre_compile', 'sre_parse', 'sub', 'subn', 'sys', 'template'] 你 也 可 以 使 用 dir 命 令 来 找 特 定 方 法 的 一 小 部 分 文 档 >>> help (re.search) Help on function search in module re: search(pattern, string, flags=0) Scan through string looking for a match to the pattern, returning a match object, or None if no match was found. >>> 然 内 置 的 文 档 不 尽, 但 在 急 需 或 没 有 网 器 和 搜 索 引 擎 的 情 况 下 用 11.8 脆 弱 代 : 当 入 数 据 是 一 种 特 定 格 式, 如 果 格 式 上 有 一 点 偏 差, 代 很 容 易 出 由 于 容 易 出, 种 代 被 称 脆 弱 代 婪 匹 配 : 正 表 式 中 + 和 * 采 用 外 向 展, 匹 配 最 大 可 能 的 字 符 串 正 表 式 106

grep: 在 大 多 数 Unix 操 作 系 中 可 以 使 用 的 命 令, 搜 索 文 本 文 件, 通 正 表 式 一 行 行 行 匹 配 命 令 的 全 称 是 通 用 正 表 式 解 析 器 (Generalized Regular Expression Parser) 正 表 式 : 表 复 搜 索 字 符 串 的 言 正 表 式 可 能 包 含 特 定 字 符 串, 指 明 搜 索 只 匹 配 开 或 尾, 以 及 其 他 多 似 的 功 能 通 配 符 : 匹 配 任 意 字 符 的 特 殊 字 符 例 如, 在 正 表 式 中, 句 点 是 一 个 通 配 符 11.9 11.1 写 一 段 程 序, 模 Unix 中 grep 命 令 的 操 作 要 求 用 入 一 个 正 表 式, 出 正 表 式 匹 配 的 文 本 行 数 $ python grep.py Enter a regular expression: ^Author mbox.txt had 1798 lines that matched ^Author $ python grep.py Enter a regular expression: ^Xmbox.txt had 14368 lines that matched ^X- $ python grep.py Enter a regular expression: java$ mbox.txt had 4218 lines that matched java$ 11.2 写 一 个 程 序, 找 以 下 形 式 的 文 本 行 使 用 正 表 式 的 findall() 函 数 抽 取 每 一 行 中 的 数 字, 算 并 出 数 字 的 平 均 Enter file:mbox.txt 38549.7949721 Enter file:mbox-short.txt 39756.9259259 正 表 式 107

第 12 章 网 程 然 中 多 示 例 重 于 取 文 件 和 索 文 件 中 的 数 据, 而 如 今 的 互 网 上 有 丰 富 的 信 息 来 源, 得 考 在 内 在 本 章 中, 我 装 成 一 个 网 器, 使 用 超 文 本 (HyperText Transport Protocol, HTTP) 索 网, 取 面 数 据 并 行 解 析 12.1 超 文 本 HTTP 网 了 整 个 网, 其 本 身 非 常 由 于 Python 内 置 了 sockets, 在 Python 程 序 中 建 立 网 接, 通 些 套 接 字 索 数 据, 得 非 常 容 易 套 接 字 很 像 文 件 不 同 的 是 它 提 供 了 个 程 序 之 的 双 向 接, 在 一 个 套 接 字 上 可 以 同 取 和 写 入 如 果 你 在 套 接 字 的 一 端 写 内 容, 套 接 字 会 把 数 据 送 一 端 的 用 程 序 如 果 从 套 接 字 取, 将 得 到 一 个 程 序 送 的 数 据 然 而, 当 套 接 字 一 端 没 有 送 任 何 数 据, 如 果 你 取 套 接 字, 果 就 只 能 等 待 如 果 套 接 字 端 的 程 序 都 在 等 待 数 据, 而 不 送 任 何 数 据, 它 就 会 僵 持 下 去 程 序 的 一 个 重 要 成 部 分 是 与 互 网 的 通, 即 具 某 种 是 一 精 确 的 集 合, 决 定 了 先 后, 做 些 什 么, 消 息 如 何, 以 及 下 一 步 来 送 等 从 某 种 意 上, 套 接 字 端 的 个 程 序 像 是 在 跳 舞, 确 保 不 会 到 方 的 脚 趾 已 有 大 量 文 档 介 网 超 文 本 原 文 如 下 : http://www.w3.org/protocols/rfc2616/rfc2616.txt 个 文 档 包 含 179, 内 容 复 尽 如 果 你 感 趣, 完 它 如 果 是 翻 看 RFC2616 的 第 36 左 右, 你 会 找 到 GET 求 的 法 如 果 仔, 你 会 是 从 网 服 器 求 文 档, 与 http://www.py4inf.com 服 器 的 80 端 口 建 立 接, 然 后 送 表 的 一 行 GET http://www.py4inf.com/code/romeo.txt HTTP/1.0 第 二 个 参 数 是 我 求 的 网, 随 后 我 送 一 个 空 白 行 网 服 器 将 文 档 的 一 些 部 信 息 和 文 档 内 容 之 后 的 空 白 行 12.2 世 界 上 最 的 网 器 解 HTTP 工 作 原 理 的 最 方 法, 也 就 是 写 一 段 非 常 的 Python 程 序 与 网 服 器 建 立 接, 遵 循 HTTP, 向 服 器 求 文 档 并 示 出 来 import socket mysock = socket.socket(socket.af_inet, socket.sock_stream) mysock.connect(('www.py4inf.com', 80)) mysock.send('get http://www.py4inf.com/code/romeo.txt HTTP/1.0\n\n') while True: data = mysock.recv(512) if ( len(data) < 1 ) : break print data mysock.close() 网 程 108

首 先, 程 序 与 服 器 http://www.py4inf.com 在 80 端 口 建 立 一 个 接, 个 程 序 扮 演 了 网 器 的 角 色 HTTP 要 求, 必 送 GET 命 令, 并 在 后 面 跟 一 个 空 白 行 送 空 白 行 之 后, 我 写 一 个 循, 从 套 接 字 中 接 收 512 个 字 符 的 数 据 片 段, 并 打 印 出 些 数 据, 直 到 没 有 数 据 可 以 入, 即 recv() 返 回 一 个 空 字 符 串 程 序 行 果 如 下 : HTTP/1.1 200 OK Date: Sun, 14 Mar 2010 23:52:41 GMT Server: Apache Last-Modified: Tue, 29 Dec 2009 01:31:22 GMT ETag: "143c1b33-a7-4b395bea" Accept-Ranges: bytes Content-Length: 167 Connection: close Content-Type: text/plain But soft what light through yonder window breaks It is the east and Juliet is the sun Arise fair sun and kill the envious moon Who is already sick and pale with grief 程 序 一 开 始 出 的 是 网 服 器 送 的 文 档 描 述 的 部 信 息 例 如,Content-Type 部 指 明 文 档 是 一 个 普 通 文 本 文 档 (text/plain) 服 器 送 了 部 信 息 之 后, 添 加 一 个 空 白 行 表 示 部 信 息 送 完, 然 后 送 的 romeo.txt 文 件 数 据 示 例 展 示 了 如 何 通 套 接 字 建 立 低 的 网 接 套 接 字 用 于 网 服 器 件 服 器 以 及 其 他 多 型 服 器 的 通 找 到 描 述 的 文 档, 写 代, 根 据 送 和 取 数 据, 要 做 的 就 么 多 了 由 于 最 常 用 的 是 HTTP( 即 Web),Python HTTP 了 的 来 支 持 网 文 档 数 据 的 取 12.3 通 HTTP 索 像 在 以 上 示 例 中, 我 取 了 一 个 包 含 行 符 的 普 通 文 本 文 件, 程 序 行 地 拷 数 据 并 示 出 来 接 下 来, 我 使 用 HTTP 写 一 个 似 的 程 序, 用 来 索 片 在 一 个 字 符 串 中 累 数 据, 截 取 部 信 息, 然 后 将 片 数 据 保 存 到 一 个 文 件 中, 程 序 代 如 下 : import socket import time mysock = socket.socket(socket.af_inet, socket.sock_stream) mysock.connect(('www.py4inf.com', 80)) mysock.send('get http://www.py4inf.com/cover.jpg HTTP/1.0\n\n') count = 0 网 程 109

picture = ""; while True: data = mysock.recv(5120) if ( len(data) < 1 ) : break # time.sleep(0.25) count = count + len(data) print len(data),count picture = picture + data mysock.close() # Look for the end of the header (2 CRLF) pos = picture.find("\r\n\r\n"); print 'Header length',pos print picture[:pos] # Skip past the header and save the picture data picture = picture[pos+4:] fhand = open("stuff.jpg","wb") fhand.write(picture); fhand.close() 程 序 行 果 如 下 : $ python urljpeg.py 2920 2920 1460 4380 1460 5840 1460 7300... 1460 62780 1460 64240 2920 67160 1460 68620 1681 70301 Header length 240 HTTP/1.1 200 OK Date: Sat, 02 Nov 2013 02:15:07 GMT Server: Apache Last-Modified: Sat, 02 Nov 2013 02:01:26 GMT ETag: "19c141-111a9-4ea280f8354b8" Accept-Ranges: bytes Content-Length: 70057 Connection: close Content-Type: image/jpeg 个 url,content-type 部 指 明 文 档 本 身 是 一 个 像 (img/jpeg) 程 序 行 完 之 后, 使 用 像 器 打 开 stuff.jpg 文 件 看 像 数 据 程 序 行 中 用 了 recv() 函 数, 每 次 不 会 得 到 5120 个 字 符 用 recv(), 通 网, 我 从 网 服 器 得 更 多 字 符 串 在 个 示 例 中, 每 一 次 得 1460 或 2920 个 字 符, 求 上 限 是 5120 个 字 符 网 速 不 同 会 致 不 同 的 果 要 注 意 的 是, 最 后 一 次 用 recv(), 在 数 据 流 束 得 到 1681 个 字, 再 下 一 个 recv() 用 得 零 度 的 字 符 串 就 是 告 我, 服 器 已 在 套 接 字 末 尾 用 了 close(), 没 有 更 多 数 据 可 送 了 把 time.sleep() 前 面 的 注 去 掉, 可 以 随 后 的 用 一 来, 每 次 相 隔 1/4 秒, 服 器 我 靠 前, 送 更 多 的 数 据 程 序 的 延 隔 行 如 下 所 示 : $ python urljpeg.py 1460 1460 5120 6580 5120 11700... 5120 62900 5120 68020 2281 70301 Header length 240 网 程 110

HTTP/1.1 200 OK Date: Sat, 02 Nov 2013 02:22:04 GMT Server: Apache Last-Modified: Sat, 02 Nov 2013 02:01:26 GMT ETag: "19c141-111a9-4ea280f8354b8" Accept-Ranges: bytes Content-Length: 70057 Connection: close Content-Type: image/jpeg 次 行 中 除 了 第 一 次 和 最 后 一 次 recv() 用, 每 次 求 新 数 据 都 会 得 到 5120 个 字 符 服 器 生 成 的 send() 求 与 程 序 生 成 的 recv() 求 之 存 在 一 个 冲 区 当 程 序 行 延 求, 在 某 些 点 上, 服 器 可 能 会 在 套 接 字 中 填 冲 区, 并 强 制 停, 直 到 程 序 开 始 清 空 存 区 送 用 或 接 收 用 的 停 行 被 称 流 量 控 制 12.4 使 用 urllib 索 网 与 通 HTTP 套 接 字 手 送 与 取 数 据 相 比,Python 中 有 一 种 更 的 解 决 方 法, 使 用 urllib 使 用 urllib, 你 可 以 将 网 看 成 一 个 文 件 只 需 指 明 需 要 索 的 网,urllib 会 理 所 有 HTPP 和 部 使 用 urllib 取 romeo.txt 文 件 的 代 如 下 : import urllib fhand = urllib.urlopen('http://www.py4inf.com/code/romeo.txt') for line in fhand: print line.strip() 网 通 urllib.urlopen 打 开 后, 我 就 可 以 把 它 当 成 一 个 文 件, 使 用 for 循 来 取 程 序 行, 我 看 到 文 件 内 容 的 出 然 部 信 息 仍 然 会 送, 但 是 urllib 代 会 理 部, 送 我 的 是 文 件 内 容 But soft what light through yonder window breaks It is the east and Juliet is the sun Arise fair sun and kill the envious moon Who is already sick and pale with grief 了 演 示 明, 我 写 一 个 程 序 来 取 romeo.txt 的 数 据, 算 文 件 中 每 个 的 率, 代 如 下 所 示 : import urllib counts = dict() fhand = urllib.urlopen('http://www.py4inf.com/code/romeo.txt') for line in fhand: words = line.split() for word in words: counts[word] = counts.get(word,0) + 1 print counts 同 地, 一 旦 打 开 了 网, 我 就 可 以 把 它 当 做 一 个 本 地 文 件 行 取 12.5 解 析 HTML 和 Web 抓 取 Python 的 urllib 常 用 法 之 一 是 网 抓 取 网 抓 取 是 写 一 个 程 序, 装 成 网 器, 索 网, 然 后 在 些 面 中 根 据 网 程 111

模 式 数 据 例 来, 搜 索 引 擎 ( 如 Google) 会 看 网 的 源 代, 抽 取 接 到 其 他 面 的 超 接, 然 后 索 些 面, 抽 取 超 接, 如 此 往 复 下 去 使 用 种 技,Google 爬 虫 几 乎 遍 了 网 上 的 所 有 面 Google 使 用 面 接 的 次 来 明 一 个 具 体 面 的 重 要 性, 在 搜 索 果 中 表 明 面 排 位 的 高 低 12.6 使 用 正 表 式 解 析 HTML HTML 解 析 的 一 个 方 法 是 使 用 正 表 式 行 重 复 搜 索, 根 据 特 定 模 式, 抽 取 出 与 之 匹 配 的 子 字 符 串 以 下 是 一 个 的 网 : <h1>the First Page</h1> <p> If you like, you can switch to the <a href="http://www.dr-chuck.com/page2.htm"> Second Page</a>. </p> 我 造 一 个 符 合 法 的 正 表 式, 匹 配 和 抽 取 以 上 网 文 本 中 的 超 接, 正 表 式 如 下 所 示 : href="http://.+?" 个 正 表 式 找 以 ref="http:// 开 的 字 符 串, 之 后 是 一 个 或 多 个 字 符.+?, 最 后 是 一 个 双 引 号.+? 表 示 以 非 婪 方 式 行 匹 配, 而 不 是 婪 方 式 非 婪 匹 配 找 到 最 小 可 能 匹 配 的 字 符 串, 婪 匹 配 找 到 最 大 可 能 匹 配 的 字 符 串 正 表 式 中 的 括 号 表 示, 我 需 要 精 确 匹 配 的 字 符 串, 程 序 代 如 下 : import urllib import re url = raw_input('enter - ') html = urllib.urlopen(url).read() links = re.findall('href="(http://.*?)"', html) for link in links: print link 正 表 式 的 findall 方 法 返 回 正 表 式 匹 配 到 的 字 符 串 列 表, 返 回 双 引 号 之 的 超 接 文 本 程 序 行 果 如 下 : python urlregex.py Enter - http://www.dr-chuck.com/page1.htm http://www.dr-chuck.com/page2.htm python urlregex.py Enter - http://www.py4inf.com/book.htm http://www.greenteapress.com/thinkpython/thinkpython.html http://allendowney.com/ http://www.py4inf.com/code http://www.lib.umich.edu/espresso-book-machine http://www.py4inf.com/py4inf-slides.zip 如 果 HTML 网 是 良 的 和 可 的, 正 表 式 会 理 地 很 漂 亮 但 是, 由 于 存 在 大 量 破 坏 性 的 HTML 网, 你 可 能 会, 使 用 正 表 式 的 解 决 方 案 可 能 会 一 些 有 效 接 或 中 止 于 坏 数 据 强 大 的 HTML 解 析 可 以 解 决 个 网 程 112

12.7 使 用 BeautifulSoup 解 析 HTML 已 有 多 Python 可 以 帮 助 你 解 析 HTML 与 抽 取 面 中 的 数 据 每 个 Python 都 有 缺 点, 根 据 需 要 行 例 来 看, 我 使 用 BeautifulSoup 来 解 析 一 些 HTML 入 和 抽 取 接 从 http://www.crummy.com 网 站 下 和 安 装 BeautifulSoup 代 你 可 以 下 和 安 装 BeautifulSoup, 或 地 将 BeautifulSoup.py 放 在 你 的 程 序 文 件 下 HTML 与 XML 看 起 来 很 像, 有 一 些 网 被 精 心 造 XML 一 般 而 言, 大 多 数 HTML 会 被 XML 解 析 器 是 格 式 不 正 确 而 整 体 拒, 致 解 析 失 BeautifulSoup 极 大 容 忍 了 HTML 的 缺 陷, 依 然 你 能 易 抽 取 所 需 的 数 据 我 使 用 urllib 取 面, 然 后 根 据 抽 取 href 属 性 的 内 容 import urllib from BeautifulSoup import * url = raw_input('enter - ') html = urllib.urlopen(url).read() soup = BeautifulSoup(html) # Retrieve all of the anchor tags tags = soup('a') for tag in tags: print tag.get('href', None) 程 序 提 示 入 一 个 网 址, 然 后 打 开 网, 取 与 数 据 到 BeautifulSoup 解 析 器, 接 下 来, 索 所 有 的, 打 印 出 每 个 的 href 属 性 内 容 python urllinks.py Enter - http://www.dr-chuck.com/page1.htm http://www.dr-chuck.com/page2.htm python urllinks.py Enter - http://www.py4inf.com/book.htm http://www.greenteapress.com/thinkpython/thinkpython.html http://allendowney.com/ http://www.si502.com/ http://www.lib.umich.edu/espresso-book-machine http://www.py4inf.com/code http://www.pythonlearn.com/ 使 用 BeautifulSoup 取 出 每 个 的 不 同 部 分, 代 如 下 : import urllib from BeautifulSoup import * url = raw_input('enter - ') html = urllib.urlopen(url).read() soup = BeautifulSoup(html) # Retrieve all of the anchor tags tags = soup('a') for tag in tags: # Look at the parts of a tag print 'TAG:',tag print 'URL:',tag.get('href', None) print 'Content:',tag.contents[0] print 'Attrs:',tag.attrs 程 序 行 果 如 下 : 网 程 113

python urllink2.py Enter - http://www.dr-chuck.com/page1.htm TAG: <a href="http://www.dr-chuck.com/page2.htm"> Second Page</a> URL: http://www.dr-chuck.com/page2.htm Content: [u'\nsecond Page'] Attrs: [(u'href', u'http://www.dr-chuck.com/page2.htm')] 些 例 子 揭 开 了 BeautifulSoup 解 析 HTML 功 能 的 冰 山 一 角 更 多 内 容 http://www.crummy.com 文 档 与 示 例 12.8 使 用 urllib 取 二 制 文 件 有, 你 需 要 索 非 文 本 ( 二 制 ) 文 件, 如 像 或 文 件 些 文 件 的 数 据 直 接 打 印 出 是 没 有 用 的, 但 可 以 通 urllib 将 URL 指 向 的 文 件 保 存 在 本 地 硬 模 式 打 开 URL, 使 用 read 方 法 下 整 个 文 档 内 容, 将 其 存 入 一 个 字 符 串 量 ( 如 img), 然 后 将 量 内 容 写 入 本 地 文 件 程 序 代 如 下 : img = urllib.urlopen('http://www.py4inf.com/cover.jpg').read() fhand = open('cover.jpg', 'w') fhand.write(img) fhand.close() 程 序 通 网 取 所 有 数 据, 将 它 存 在 算 机 内 存 的 img 量 中, 然 后 打 开 文 件 cover.jpg, 将 数 据 写 入 到 硬 中 如 果 文 件 大 小 小 于 算 机 内 存 容 量, 个 程 序 将 会 成 功 行 然 而, 如 果 是 一 个 大 型 音 或 文 件, 当 算 机 耗 尽 内 存, 个 程 序 可 能 会 崩 或 行 极 慢 了 避 免 耗 尽 内 存, 我 以 区 ( 或 冲 区 ) 索 数 据, 在 索 下 一 个 区 前 将 当 前 区 写 入 磁 一 来, 程 序 就 可 以 取 任 意 大 小 的 文 件, 无 需 担 心 耗 尽 算 机 的 全 部 内 存 import urllib img = urllib.urlopen('http://www.py4inf.com/cover.jpg') fhand = open('cover.jpg', 'w') size = 0 while True: info = img.read(100000) if len(info) < 1 : break size = size + len(info) fhand.write(info) print size,'characters copied.' fhand.close() 在 个 示 例 中, 每 次 取 100,000 个 字 符, 从 网 索 下 一 批 100,000 个 字 符 数 据 之 前, 先 将 些 字 符 写 入 cover.jpg 文 件 程 序 行 果 如 下 : python curl2.py 568248 characters copied. 如 果 是 Unix 或 Mac 算 机, 你 可 以 使 用 操 作 系 内 置 命 令 来 行 个 操 作 : curl -O http://www.py4inf.com/cover.jpg 网 程 114

curl 命 令 是 copy URL 的 写, 个 例 子 文 件 命 名 curl1.py 和 curl2.py, 可 以 从 http://www.py4inf.com/code 下 它 了 culr 命 令 相 似 的 功 能 curl3.py 示 例 程 序 以 更 高 效 的 方 式 完 成 二 制 文 件 的 写, 种 模 式 可 能 你 自 己 写 程 序 有 所 帮 助 12.9 BeautifulSoup: 一 个 用 于 HTML 文 档 解 析 与 数 据 抽 取 的 Python 它 能 理 大 多 数 在 器 中 通 常 被 忽 略 的, 存 在 缺 陷 的 HTML BeautifulSoup 代 http:// 从 www.crummy.com 网 站 下 端 口 : 当 与 服 器 建 立 套 接 字 接, 服 器 告 用 程 序 行 通 所 采 用 的 数 字 例 如, 网 流 量 通 常 使 用 80 端 口, 子 件 流 量 使 用 25 端 口 抓 取 : 把 程 序 装 成 网 器, 索 网, 找 网 中 的 内 容 通 常, 程 序 会 根 据 一 个 网 中 的 接 找 到 下 一 个 网, 网 网 或 社 交 网 的 遍 套 接 字 : 个 用 程 序 之 的 网 接, 彼 此 可 以 送 与 接 收 数 据 爬 虫 : 网 搜 索 引 擎 的 索 面, 然 后 从 面 所 有 接 再 次 起 索, 如 此 往 复 下 去, 直 到 它 索 到 网 上 的 几 乎 所 有 面 些 面 将 用 于 建 索 引, 供 搜 索 之 用 12.10 12.1 修 改 套 接 字 程 序 socket1.py, 提 示 用 入 URL, 它 可 以 取 任 何 网 你 可 以 使 用 split( / ) 拆 分 URL, 抽 取 出 套 接 字 connect 用 的 主 机 名 使 用 try 和 except 增 加, 理 用 入 不 恰 当 的 网 址 或 不 存 在 的 URL 种 情 况 12.2 修 改 套 接 字 程 序, 接 收 到 的 字 符 数 与 3000 个 字 符 之 后 未 示 的 文 本 程 序 索 整 个 文 档, 字 符 数 并 示 在 文 档 尾 12.3 使 用 urllib 重 复 之 前 的 :(1) 从 URL 中 索 文 档 ;(2) 示 3000 个 字 符 ;(3) 文 档 的 字 符 数 里 不 必 担 心 部 信 息, 只 示 文 档 内 容 中 前 3000 个 字 符 即 可 12.4 修 改 ulrlinks.py 程 序, 索 到 的 HTML 文 档 抽 取 和 段 落 (p), 在 程 序 出 中 示 段 落 数 量 不 要 示 段 落 文 本, 段 落 数 在 网 和 复 网 上 程 序 12.5 ( ) 修 改 socket 程 序, 使 其 只 示 部 和 空 行 之 后 的 索 数 据 住,recv 是 按 照 字 符 ( 包 括 行 及 所 有 ) 而 非 行 来 接 收 的 网 程 115

第 13 章 Web Services 掌 握 了 通 HTTP 写 文 档 索 与 解 析 程 序 之 后, 接 下 来 我 自 己 建 的 文 档, 开 一 种 其 他 用 程 序 可 用 的 文 档 服, 就 不 是 一 件 很 苦 的 事 情 了 里 的 文 档 不 是 示 在 网 器 中 的 HTML 网 网 数 据 交 包 括 种 常 格 式 : 可 展 言 XML(eXtensible Markup Language) 和 JSON(JavaScript Object Notation) XML 已 使 用 很, 适 合 于 交 文 档 型 的 数 据 当 程 序 彼 此 之 只 需 要 交 字 典 列 表 或 其 他 内 部 信 息, 一 般 会 使 用 JSON 接 下 来 分 介 种 格 式 13.1 可 展 言 XML XML 与 HTML 看 起 非 常 像, 但 XML 比 HTML 的 化 程 度 更 高 下 面 是 一 个 XML 文 档 示 例 : <person> <name>chuck</name> <phone type="intl"> +1 734 303 4456 </phone> <email hide="yes"/> </person> 通 常 可 以 把 XML 文 档 想 象 成 一 个, 有 助 于 理 解 示 例 中 是 person, 其 他 是 它 的 子 点, 如 phone 13.2 XML 解 析 下 面 是 一 个 的 示 例 程 序, XML 文 件 行 解 析, 从 中 提 取 一 些 数 据 元 素 : import xml.etree.elementtree as ET data = "' <person> <name>chuck</name> <phone type="intl"> +1 734 303 4456 </phone> <email hide="yes"/> </person>"' tree = ET.fromstring(data) print 'Name:',tree.find('name').text print 'Attr:',tree.find('email').get('hide') 用 fromstring 将 XML 的 字 符 串 表 示 一 XML 点 当 XML 被 一, 我 就 有 一 系 列 方 法 来 抽 取 XML 中 的 数 据 片 段 Web Services 116

使 用 find 函 数 XML 行 搜 索, 索 出 匹 配 特 定 的 点 每 个 点 包 含 一 些 文 本, 一 些 属 性 ( 例 如 藏 的 ) 以 及 一 些 子 点 每 个 点 都 可 以 成 点 的 点 Name: Chuck Attr: yes XML 解 析 器, 例 如 ElementTree, 可 以 理 多 XML 有 效 性, 我 无 需 操 心 XML 法 就 可 以 抽 取 需 要 的 XML 数 据 片 段 由 于 示 例 的 XML 于, 体 不 出 一 13.3 点 循 通 常,XML 会 有 多 个 点, 我 需 要 写 一 个 循 来 理 所 有 点 下 面 的 程 序 使 用 循 找 出 user 点 : import xml.etree.elementtree as ET input = "' <stuff> <users> <user x="2"> <id>001</id> <name>chuck</name> </user> <user x="7"> <id>009</id> <name>brent</name> </user> </users> </stuff>"' stuff = ET.fromstring(input) lst = stuff.findall('users/user') print 'User count:', len(lst) for item in lst: print 'Name', item.find('name').text print 'Id', item.find('id').text print 'Attribute', item.get('x') 使 用 Python 列 表 来 表 示 XML 中 user 的 子, findall 方 法 索 个 列 表 然 后, 写 一 个 循, 索 出 每 一 个 user 点, 打 印 出 name 和 id 的 文 本 元 素, 以 及 user 点 的 x 属 性 User count: 2 Name Chuck Id 001 Attribute 2 Name Brent Id 009 Attribute 7 13.4 JavaScript 象 - JSON JSON 格 式 的 灵 感 来 自 于 JavaScript 言 的 象 与 数 格 式 Python 的 出 早 于 JavaScript,Python 的 字 典 与 列 表 法 JSON 言 有 一 定 影 所 以,JSON 格 式 可 Python 列 表 与 字 典 的 合 上 面 的 XML 示 例 使 用 JSON 格 式 来 表 示, 如 下 代 所 示, 者 大 致 等 价 : { "name" : "Chuck", Web Services 117

"phone" : { "type" : "intl", "number" : "+1 734 303 4456" }, "email" : { "hide" : "yes" } } 你 会 注 意 到 一 些 差 异 首 先,XML 中 phone 有 一 个 intl 属 性, 在 JSON 里 理 成 外,XML 的 person 没 有 了, 取 而 代 之 的 是 一 大 括 号 由 于 JSON 比 XML 功 能 少, 所 以 JSON 的 比 XML 但 是,JSON 的 在 于, 它 直 接 映 射 成 字 典 与 列 表 的 合 几 乎 所 有 程 言 与 Python 的 字 典 和 列 表 都 存 在 某 种 程 度 上 的 等 价 关 系, 所 以 JSON 是 个 作 用 程 序 之 非 常 合 适 的 数 据 交 格 式 与 XML 相 比,JSON 相, 正 迅 速 成 用 程 序 之 数 据 交 格 式 的 不 二 13.5 JSON 解 析 通 字 典 ( 象 ) 与 列 表 的 嵌 套 来 造 我 需 要 的 JSON 个 示 例 中 用 的 列 表 由 集 合 成 ( 也 就 是 一 个 字 典 ) 因 此, 我 有 了 一 个 字 典 列 表 在 下 面 的 程 序 中, 我 使 用 内 置 的 json 来 解 析 JSON, 取 其 中 的 数 据 仔 比 等 价 的 XML 数 据 和 上 面 的 代, 有 一 点 必 提 前 知,JSON 的 少 我 最 得 到 的 列 表 包 含 用 信 息, 每 个 用 的 信 息 是 集 合 JSON 的 点 是 格 式, 缺 点 是 自 描 述 能 力 不 强 import json input = "' [ { "id" : "001", "x" : "2", "name" : "Chuck" }, { "id" : "009", "x" : "7", "name" : "Brent" } ]"' info = json.loads(input) print 'User count:', len(info) for item in info: print 'Name', item['name'] print 'Id', item['id'] print 'Attribute', item['x'] 从 解 析 后 的 JSON 与 XML 分 抽 取 数 据 的 段 代 行 比, 你 会 json.loads() 得 到 一 个 Python 列 表, 通 for 循 行 遍, 列 表 的 每 个 数 据 是 一 个 Python 字 典, 其 中 使 用 了 Python 索 引 操 作 符 来 抽 取 每 个 用 的 各 个 字 JSON 解 析 后, 我 就 得 到 了 原 生 的 Python 象 与 由 于 返 回 的 数 据 就 是 的 原 生 Python, 就 没 必 要 使 用 JSON 深 入 解 析 JSON 了 程 序 行 果 如 下, 与 上 面 的 XML 版 本 几 乎 相 同 User count: 2 Name Chuck Id 001 Attribute 2 Name Brent Web Services 118

Id 009 Attribute 7 之,Web Service 的 行 展 是 从 XML 向 JSON 由 于 JSON 足, 能 直 接 映 射 到 程 言 已 有 的 原 生 数 据,JSON 的 使 用 解 析 与 数 据 抽 取 得 更 但 是,XML 比 JSON 在 自 我 描 述 方 面 更 强, 因 此 在 某 些 用 程 序 中 XML 仍 然 有 一 定 例 如, 大 多 数 文 字 理 器 内 部 存 文 档 采 用 XML 而 不 是 JSON 13.6 用 程 接 口 API 我 已 学 了 通 超 文 本 HTTP 在 用 程 序 之 交 数 据, 了 解 了 使 用 XML 与 JSON 在 些 用 程 序 之 送 与 接 收 复 数 据 的 表 示 方 法 下 一 步 是 使 用 些 技 在 用 程 序 之 定 与 合 同 用 程 序 之 合 同 的 一 般 名 称 是 用 程 序 接 口 或 APIs 当 我 使 用 一 个 API, 用 程 序 通 常 会 提 供 一 可 供 其 他 用 程 序 使 用 的 服 用 程 序 布 的 APIs( 即 ) 在 服 必 遵 守 当 我 开 始 建 自 己 的 用 程 序, 功 能 上 要 能 其 他 用 程 序 提 供 的 服, 种 方 式 称 面 向 服 的 架 SOA(Service- Oriented Architecture) SOA 方 式 是 用 程 序 使 用 其 他 用 程 序 服 的 称 非 SOA 方 式 是 用 程 序 作 一 独 立 的 程 序, 自 身 包 含 程 序 行 中 所 需 的 所 有 代 互 网 用 中 存 在 多 SOA 例 我 可 以 在 一 个 网 站 上 完 成 旅 行 机 票 与 酒 店 定 以 及 租 等 一 系 列 活 酒 店 数 据 没 有 存 在 航 空 公 司 的 算 机 上 相 反, 航 空 公 司 的 算 机 与 酒 店 的 算 机 服 合 同, 索 酒 店 数 据, 并 呈 用 当 用 使 用 航 空 公 司 的 网 站 了 一 家 酒 店, 航 空 公 司 的 网 站 使 用 酒 店 系 的 Web Service 来 完 成 当 涉 及 整 个 交 易 的 信 用 卡 支 付, 仍 然 会 有 其 他 算 机 参 与 到 个 程 面 向 服 的 架 有 多 点, 其 中 包 括 :(1) 数 据 始 只 存 在 一, 酒 店 情 况 来 特 重 要, 我 不 希 望 出 多 次 提 交 ;(2) 数 据 的 有 者 能 置 数 据 的 使 用 基 于 些 点,SOA 系 必 精 心, 以 到 具 良 好 的 性 能 与 足 用 的 需 求 用 程 序 通 网 布 一 可 用 的 API 服, 我 称 之 Web Services 13.7 Google 地 理 Web Service Google 的 Web Service 非 常 秀, 我 能 充 分 利 用 其 大 的 地 理 信 息 数 据 我 可 以 向 Google 的 地 理 API 提 交 如 Ann Arbor, MI 的 地 理 搜 索 字 符 串 Google 会 根 据 搜 索 字 符 串 返 回 最 佳 猜, 在 地 上 告 我 想 找 的 地 方 以 及 附 近 的 地 性 建 筑 地 理 服 是 免 的, 但 有 次 数 限 制, 不 能 在 商 用 程 序 中 无 限 制 使 用 如 果 有 一 些 数 据, 其 中 被 者 在 自 Web Services 119

由 格 式 的 入 框 中 入 了 一 个 地 址, 你 就 可 以 使 用 个 API 清 洗 些 数 据, 效 果 会 很 不 当 使 用 似 Google 地 理 API 的 免 API, 你 需 要 遵 守 些 源 的 使 用 定 如 果 有 太 多 用 用 API,Google 会 关 或 大 幅 度 免 服 通 服 的 在 文 档 了 解 使 用 方 法 不, 个 操 作 非 常, 可 以 直 接 在 器 中, 在 地 址 入 如 下 URL: http://maps.googleapis.com/maps/api/geocode/json?sensor=false &address=ann+arbor%2c+mi 粘 到 器 之 前, 确 保 是 原 始 的 URL, 移 除 URL 中 的 任 何 空 格 下 面 是 一 个 用 程 序, 提 示 用 入 一 个 搜 索 字 符 串, 用 Google 的 地 理 API, 从 返 回 的 JSON 中 抽 取 信 息 import urllib import json serviceurl = 'http://maps.googleapis.com/maps/api/geocode/json?' while True: address = raw_input('enter location: ') if len(address) < 1 : break url = serviceurl + urllib.urlencode({'sensor':'false', 'address': address}) print 'Retrieving', url uh = urllib.urlopen(url) data = uh.read() print 'Retrieved',len(data),'characters' try: js = json.loads(str(data)) except: js = None if 'status' not in js or js['status']!= 'OK': print '==== Failure To Retrieve ====' print data continue print json.dumps(js, indent=4) lat = js["results"][0]["geometry"]["location"]["lat"] lng = js["results"][0]["geometry"]["location"]["lng"] print 'lat',lat,'lng',lng location = js['results'][0]['formatted_address'] print location 程 序 取 入 的 搜 索 字 符 串, 将 其 作 合 适 的 参 数, 建 URL, 使 用 urllib 从 Google 地 理 API 索 文 本 内 容 与 固 定 的 网 不 同, 里 得 到 的 数 据 取 决 于 送 的 参 数 与 Google 服 器 中 存 的 地 理 数 据 一 旦 取 到 JSON 数 据, 我 使 用 json 其 行 解 析, 做 一 些 以 确 保 收 到 良 好 的 数 据, 然 后 抽 取 我 需 要 的 数 据 程 序 行 果 如 下 ( 下 面 只 展 示 了 返 回 的 部 分 JSON 数 据 ): $ python geojson.py Enter location: Ann Arbor, MI Retrieving http://maps.googleapis.com/maps/api/ geocode/json?sensor=false&address=ann+arbor%2c+mi Retrieved 1669 characters { "status": "OK", "results": [ { "geometry": { "location_type": "APPROXIMATE", "location": { Web Services 120

"lat": 42.2808256, "lng": -83.7430378 } }, "address_components": [ { "long_name": "Ann Arbor", "types": [ "locality", "political" ], "short_name": "Ann Arbor" } ], "formatted_address": "Ann Arbor, MI, USA", "types": [ "locality", "political" ] } ] } lat 42.2808256 lng -83.7430378 Ann Arbor, MI, USA Enter location: 你 可 以 下 http://www.py4inf.com/code/geojson.py 和 http://www.py4inf.com/code/geoxml.py 个 文 件, 搞 清 楚 Google 地 理 API 的 JSON 与 XML 之 的 差 13.8 安 全 与 API 用 法 通 常 情 况 下, 你 需 要 某 种 型 的 API 密 才 能 服 提 供 者 的 API 的 初 衷 是 服 提 供 者 想 要 知 道 在 使 用 他 的 服, 以 及 每 个 用 的 使 用 情 况 可 能 他 提 供 免 服, 但 会 根 据 服 次 收, 或 者 在 特 定 段 限 制 个 体 用 的 求 数 量 在 一 些 情 况 中, 你 一 旦 得 到 API 密, 在 用 API 只 需 将 密 作 POST 数 据 的 一 部 分, 或 者 作 URL 的 一 个 参 数 在 一 些 情 况 中, 服 提 供 者 了 增 加 求 来 源 的 保 性, 他 希 望 你 使 用 共 享 密 与 密 方 式 送 加 密 的 名 信 息 互 网 中 名 求 普 遍 采 用 OAuth 技 有 关 OAuth http://www.oauth.net 随 着 Twitter API 越 来 越 有 价,Twitter 从 免 公 开 的 API 向 每 个 API 求 需 要 OAuth 名 得 幸 的 是, 多 方 便 的 OAuth 可 以 免 使 用 你 可 以 不 必 技 范 和 从 零 写 OAuth 的 程 些 的 复 性 与 丰 富 程 度 不 一 OAuth 网 站 提 供 各 种 OAuth 信 息 下 面 一 段 示 例 程 序 需 要 从 http://www.py4inf.com/code 下 三 个 文 件 twurl.py hidden.py oauth.py 和 twitter1.py, 把 它 放 在 一 个 文 件 下 了 能 使 用 些 程 序, 需 要 一 个 Twitter 号, 你 的 Python 代 作 Twitter 的 一 个 用 得 以 授, 建 key secret token 与 token secret 通 修 改 hidden.py, 将 四 个 字 符 串 予 文 件 中 合 适 的 量 def auth() : return { "consumer_key" : "h7l...gng", "consumer_secret" : "dnk...7q", "token_key" : "101...GI", "token_secret" : "H0yM...Bo" } Twitter 的 Web Service 通 URL, 如 下 所 示 : https://api.twitter.com/1.1/statuses/user_timeline.json 所 有 的 安 全 信 息 添 加 完 之 后, 完 整 的 URL 如 下 : Web Services 121

https://api.twitter.com/1.1/statuses/user_timeline.json?count=2 &oauth_version=1.0&oauth_token=101...sgi&screen_name=drchuck &oauth_nonce=09239679&oauth_timestamp=1380395644 &oauth_signature=rlk...bod&oauth_consumer_key=h7lu...gng &oauth_signature_method=hmac-sha1 如 果 想 了 解 OAuth 安 全 需 求 的 各 种 参 数 含, OAuth 技 范 个 程 序 Twitter, 藏 了 文 件 oauth.py 与 twurl.py 中 所 有 复 我 只 需 置 hidden.py 中 的 加 密 信 息, 然 后 把 求 的 URL 送 twurl.augment() 函 数, 代 会 帮 我 添 加 URL 需 要 的 所 有 参 数 程 序 (twitter1.py) 索 了 特 定 Twitter 用 的, 以 JSON 格 式 返 回 一 个 字 符 串 我 打 印 出 字 符 串 前 250 个 字 符 import urllib import twurl TWITTER_URL='https://api.twitter.com/1.1/statuses/user_timeline.json' while True: print " acct = raw_input('enter Twitter Account:') if ( len(acct) < 1 ) : break url = twurl.augment(twitter_url, {'screen_name': acct, 'count': '2'} ) print 'Retrieving', url connection = urllib.urlopen(url) data = connection.read() print data[:250] headers = connection.info().dict # print headers print 'Remaining', headers['x-rate-limit-remaining'] 程 序 行 果 如 下 : Enter Twitter Account:drchuck Retrieving https://api.twitter.com/1.1/... [{"created_at":"sat Sep 28 17:30:25 +0000 2013"," id":384007200990982144,"id_str":"384007200990982144", "text":"rt @fixpert: See how the Dutch handle traffic intersections: http:\/\/t.co\/tiivwtehj4\n#brilliant", "source":"web","truncated":false,"in_rep Remaining 178 Enter Twitter Account:fixpert Retrieving https://api.twitter.com/1.1/... [{"created_at":"sat Sep 28 18:03:56 +0000 2013", "id":384015634108919808,"id_str":"384015634108919808", "text":"3 months after my freak bocce ball accident, my wedding ring fits again! :)\n\nhttps:\/\/t.co\/2xmhpx7kgx", "source":"web","truncated":false, Remaining 177 Enter Twitter Account: Twitter 返 回 数 据 的 同, 返 回 了 HTTP 部 中 求 的 元 数 据 特 殊 的 部 x-rate-limit-remaining 表 明, 在 短 切 断 之 前 我 能 起 的 求 数 量, 就 可 以 知 道 每 次 API 求 中 剩 余 的 索 次 数 在 下 面 例 子 中, 我 索 一 个 用 的 Twitter 朋 友, 解 析 返 回 的 JSON, 抽 取 朋 友 信 息 在 解 析 和 4 格 的 工 整 打 印 之 后 出 JSON 文 件 当 需 要 抽 取 更 多 字 段, 出 的 数 据 可 供 我 解 import urllib import twurl import json Web Services 122

TWITTER_URL = 'https://api.twitter.com/1.1/friends/list.json' while True: print " acct = raw_input('enter Twitter Account:') if ( len(acct) < 1 ) : break url = twurl.augment(twitter_url, {'screen_name': acct, 'count': '5'} ) print 'Retrieving', url connection = urllib.urlopen(url) data = connection.read() headers = connection.info().dict print 'Remaining', headers['x-rate-limit-remaining'] js = json.loads(data) print json.dumps(js, indent=4) for u in js['users'] : print u['screen_name'] s = u['status']['text'] print ' ',s[:50] 由 于 JSON 是 Python 列 表 与 字 典 的 嵌 套 集 合, 我 可 以 合 使 用 索 引 操 作 与 for 循 操 作, 使 用 很 少 的 Python 代 遍 返 回 的 数 据 程 序 行 果 如 下 ( 方 便 面 示, 一 些 数 据 被 ): Enter Twitter Account:drchuck Retrieving https://api.twitter.com/1.1/friends... Remaining 14 { "next_cursor": 1444171224491980205, "users": [ { "id": 662433, "followers_count": 28725, "status": { "text": "@jazzychad I just bought one..", "created_at": "Fri Sep 20 08:36:34 +0000 2013", "retweeted": false, }, "location": "San Francisco, California", "screen_name": "leahculver", "name": "Leah Culver", }, { "id": 40426722, "followers_count": 2635, "status": { "text": "RT @WSJ: Big employers like Google...", "created_at": "Sat Sep 28 19:36:37 +0000 2013", }, "location": "Victoria Canada", "screen_name": "_valeriei", "name": "Valerie Irvine", ], "next_cursor_str": "1444171224491980205" } leahculver @jazzychad I just bought one.. _valeriei RT @WSJ: Big employers like Google, AT&T are h ericbollens RT @lukew: sneak peek: my LONG take on the good &a halherzog Learning Objects is 10. We had a cake with the LO, scweeker @DeviceLabDC love it! Now where so I get that "etc Enter Twitter Account: Web Services 123

在 出 的 最 后, 我 看 到 for 循 取 了 Twitter 号 drchuck 的 5 位 新 近 朋 友, 打 印 出 每 位 朋 友 的 最 近 状 返 回 的 JSON 中 有 更 多 数 据 可 用 此 外, 如 果 仔 看 程 序 出, 你 会, 特 定 号 的 找 到 他 的 朋 友 与 在 一 个 段 的 求 数 量 有 不 同 的 限 制 些 安 全 的 API 密 Twitter 有 充 分 信 心, 他 知 道 在 使 用 他 的 API 以 及 数 据 使 用 情 况 限 制 我 可 以 做 一 些 的 个 人 数 据 索, 但 不 能 用 于 建 每 天 有 百 万 API 数 据 的 品 13.9 API: 用 程 序 接 口 用 程 序 之 的 合 同, 定 了 个 用 件 之 交 互 的 模 式 ElementTree: 用 于 解 析 XML 数 据 的 Python 内 置 JSON:JavaScript Object Notation 基 于 JavaScript 象 法 的 化 数 据 格 式 REST: 表 述 性 状 移 一 种 Web Service 格, 通 HTTP 提 供 用 程 序 的 源 SOA: 面 向 服 的 架 用 程 序 由 跨 网 接 的 件 成 XML: 可 展 言 化 数 据 格 式 13.10 13.1 修 改 http://www.py4inf.com/code/geojson.py 或 http://www.py4inf.com/code/geoxml.py 文 件, 从 索 到 的 数 据 中 打 印 出 2 位 字 符 的 国 家 代 添 加, 确 保 国 家 代 不 存 在 的 异 常 理 当 程 序 正 常 工 作 了, 搜 索 Atlantic Ocean, 程 序 可 以 理 不 属 于 任 何 国 家 的 地 理 位 置 Web Services 124

第 14 章 数 据 与 化 言 SQL 14.1 什 么 是 数 据 数 据 是 的 存 数 据 的 文 件 从 个 意 上, 大 多 数 数 据 的 方 式 与 字 典 似, 数 据 与 之 的 映 射 数 据 与 字 典 的 最 大 区 在 于, 数 据 存 在 磁 ( 或 其 他 永 久 存 器 ) 上, 程 序 行 束 后 数 据 会 永 久 存 在 正 是 由 于 数 据 存 在 永 久 存 上, 它 能 存 的 数 据 多 于 字 典 字 典 受 到 算 机 内 存 大 小 的 限 制 与 字 典 似, 数 据 件 被 快 速 保 留 插 入 的 与 的 数 据, 即 使 是 大 量 数 据 的 情 况 亦 如 此 数 据 件 通 添 加 的 数 据 建 索 引 来 性 能, 算 机 可 以 快 速 跳 到 特 定 数 据 广 泛 用 的 数 据 系 包 括 Oracle MySQL Microsoft SQL Server PostgreSQL 和 SQLite 本 关 注 SQLite, 因 它 是 一 个 非 常 通 用 的 数 据, 而 且 已 内 建 在 Python SQLite 被 嵌 入 到 其 他 用 程 序, 提 供 用 程 序 内 的 数 据 支 持 例 如,Firefox 器 把 SQLite 数 据 作 内 部 使 用, 其 他 很 多 品 也 做 http://sqlite.org/ SQLite 非 常 适 合 信 息 科 学 中 的 一 些 数 据 理, 比 如 本 章 介 的 Twitter 爬 虫 用 14.2 数 据 概 念 初 次 接 触 数 据, 可 将 其 多 个 工 作 表 的 子 表 格 数 据 的 主 要 数 据 包 括 表 行 与 列 在 关 系 型 数 据 中, 表 行 与 列 的 定 关 系 元 与 属 性 本 章 将 使 用 非 化 14.3 SQLite 管 理 器 (Firefox 插 件 ) 本 章 重 点 使 用 Python SQLite 数 据 文 件 行 操 作, 多 操 作 可 以 用 SQLite 数 据 管 理 器 ( 一 个 Firefox 插 件 ) 更 方 便 地 完 成 免 下 地 址 如 下 : https://addons.mozilla.org/en-us/firefox/addon/sqlite-manager/ 使 用 Firefox 器 可 以 在 数 据 中 松 建 表 插 入 数 据 数 据 以 及 行 的 SQL 从 某 种 意 上, 在 文 本 文 件 的 理 方 面, 数 据 管 理 器 与 文 本 器 似 如 果 要 文 本 文 件 行 少 量 修 改 操 作, 你 可 以 在 文 本 器 中 打 开 它, 并 根 据 需 要 修 改 如 果 要 文 本 文 件 行 大 量 修 改, 通 常 需 要 写 一 个 的 Python 程 序 似 的, 数 据 同 存 在 相 同 的 模 式 在 数 据 管 理 器 中 行 一 些 操 作, 在 Python 中 可 以 方 便 地 理 一 些 复 操 作 14.4 建 一 数 据 的 表 数 据 与 化 言 SQL 125

与 Python 的 列 表 与 字 典 相 比, 数 据 需 要 更 多 的 定 1 建 一 个 数 据 的 表, 我 必 根 据 每 一 列 存 的 数 据 情 况, 先 在 数 据 中 定 表 的 每 一 列 名 称 和 数 据 型 数 据 件 知 道 了 每 一 列 的 数 据 型, 根 据 特 定 数 据 型, 它 可 以 最 有 效 的 数 据 存 与 索 方 法 以 下 网 址 介 了 SQLite 支 持 的 各 种 数 据 型 : http://www.sqlite.org/datatypes.html 一 开 始 就 定 好 数 据 可 能 不 是 很 方 便, 但 是 做 的 好 是, 当 数 据 包 含 大 量 数 据 可 以 提 供 快 速 的 数 据 以 下 代 建 了 一 个 数 据 文 件 和 有 列 的 Tracks 表 import sqlite3 conn = sqlite3.connect('music.sqlite3') cur = conn.cursor() cur.execute('drop TABLE IF EXISTS Tracks ') cur.execute('create TABLE Tracks (title TEXT, plays INTEGER)') conn.close() connect 操 作 建 立 了 与 当 前 目 中 music.sqlite3 数 据 文 件 的 接 如 果 文 件 不 存 在, 建 它 之 所 以 称 接, 因 数 据 有 存 在 独 的 数 据 服 器 上, 与 我 行 的 用 程 序 不 在 同 一 个 服 器 上 在 个 示 例 中, 数 据 作 一 个 本 地 文 件, 与 Python 代 在 同 一 个 目 下 游 (cursor) 似 一 个 文 件 句 柄, 可 以 数 据 中 的 数 据 行 操 作 当 理 文 本 文 件,cursor() 的 用 与 open() 方 法 相 似 当 有 个 游, 我 使 用 execute() 方 法, 开 始 数 据 的 内 容 行 命 令 数 据 命 令 使 用 的 言, 在 多 数 据 厂 商 中 已 准 化, 用 只 需 学 一 种 数 据 言 即 可 数 据 言 称 化 言, 称 SQL http://en.wikipedia.org/wiki/sql 在 个 例 子 中, 我 数 据 行 条 SQL 命 令 按 照 例, 我 用 大 写 示 SQL 关, 其 他 部 分 如 表 和 列 名 示 小 写 如 果 Track 表 已 存 在, 第 一 条 SQL 命 令 就 移 除 Tracks 表 一 做 法 可 以 我 反 复 行 相 同 的 程 序 来 建 Tracks 表, 而 不 会 致 不 需 要 注 意 的 是,DROP TABLE 命 令 会 除 表 以 及 数 据 中 表 的 所 有 内 容, 也 就 是 没 有 撤 的 可 能 cur.execute('drop TABLE IF EXISTS Tracks ') 第 二 条 命 令 建 Tracks 表, 包 括 文 本 型 的 title 列 与 整 数 型 的 plays 列 数 据 与 化 言 SQL 126

cur.execute('create TABLE Tracks (title TEXT, plays INTEGER)') 在, 我 已 建 好 Tracks 表, 接 下 来 使 用 SQL 的 INSERT 操 作, 向 表 中 添 加 一 些 数 据 我 再 次 与 数 据 建 立 接, 得 游 (cursor) 通 游 行 SQL 命 令 SQL 的 INSERT 命 令 表 明 所 使 用 的 表, 通 列 字 段 来 定 新 列,(title, plays) 后 面 跟 VALUES 具 体 的 列, 从 而 生 一 个 新 行 我 指 定 (?,?), 表 示 通 第 二 个 参 数 的 一 个 元 ( My Way, 15) 来, 最 后 用 execute() 方 法 import sqlite3 conn = sqlite3.connect('music.sqlite3') cur = conn.cursor() cur.execute('insert INTO Tracks (title, plays) VALUES (?,? )', ( 'Thunderstruck', 20 ) ) cur.execute('insert INTO Tracks (title, plays) VALUES (?,? )', ( 'My Way', 15 ) ) conn.commit() print 'Tracks:' cur.execute('select title, plays FROM Tracks') for row in cur : print row cur.execute('delete FROM Tracks WHERE plays < 100') conn.commit() cur.close() 首 先, 我 向 表 中 插 入 行, 使 用 commit() 提 交 命 令 将 数 据 写 入 数 据 文 件 然 后, 我 用 SELECT 命 令 索 插 入 表 中 的 行 SELECT 命 令 首 先 指 定 (title, plays) 列, 之 后 是 数 据 索 的 来 源 表 行 SELECT 句 后, 游 可 以 我 用 for 句 行 循 了 提 高 效 率, 当 行 SELECT 句, 游 并 不 会 从 数 据 中 取 所 有 数 据 相 反, 数 据 是 在 for 循 按 需 取 程 序 行 果 如 下 : Tracks: (u'thunderstruck', 20) (u'my Way', 15) for 循 找 到 行, 每 一 行 是 一 个 Python 元, 其 中 第 一 个 是 歌 曲 名 称 (title), 第 二 个 是 播 放 次 数 (plays) 不 用 担 心,title 字 符 串 以 u 开 明 字 符 串 使 用 Unicode, 即 能 存 非 拉 丁 字 符 集 在 程 序 末 尾, 我 行 SQL 的 DELETE 命 令, 除 才 建 的 行, 以 便 可 以 反 复 行 个 程 序 DELETE 命 令 使 用 了 WHERE 子 句, 用 来 表 一 个 条 件, SQL 命 令 在 数 据 中 只 条 件 匹 配 的 行 行 操 作 在 本 示 例 中, 条 件 用 于 所 有 行, 因 此 我 可 以 清 空 表, 反 复 行 程 序 在 DELETE 命 令 行 后, 使 用 commit() 提 交 命 令 将 数 据 从 数 据 中 除 14.5 化 言 SQL 小 数 据 与 化 言 SQL 127

至 此, 我 在 Python 示 例 中 使 用 了 化 言, 介 了 一 些 SQL 命 令 的 基 本 知 本 介 SQL 言, 要 介 SQL 法 然 数 据 行 中 存 在 多 数 据 厂 商, 但 化 言 SQL 的 准 化 使 得 不 同 厂 商 之 的 数 据 系 可 以 行 数 据 互 通 与 移 植 关 系 型 数 据 由 表 行 与 列 成 列 的 常 字 段 型 包 括 文 本 数 与 日 期 数 据 当 建 表, 需 要 指 明 列 的 名 称 与 字 段 型 : CREATE TABLE Tracks (title TEXT, plays INTEGER) 使 用 SQL 的 INSERT 命 令 向 表 中 插 入 一 行 : INSERT INTO Tracks (title, plays) VALUES ('My Way', 15) INSERT 句 指 定 表 的 名 称, 之 后 是 想 要 插 入 新 行 的 字 段 ( 列 ) 的 列 表, 然 后 是 VALUES 关 及 其 后 面 每 个 字 段 的 列 表 SQL 的 SELECT 命 令 从 数 据 中 索 行 与 列 SELECT 句 指 定 想 要 索 的 列,WHERE 子 句 用 于 出 符 合 条 件 的 行 外, 可 的 ORDER BY 子 句 控 制 返 回 的 行 的 示 序 SELECT * FROM Tracks WHERE title = 'My Way' * 星 号 表 示 从 数 据 返 回 WHERE 子 句 匹 配 到 的 行 的 所 有 列 注 意, 与 Python 不 同 的 是,SQL 的 WHERE 子 句 使 用 一 个 等 号 表 示 相 等, 而 不 是 个 等 号 WHERE 子 句 的 其 他 操 作 符 包 括 < > <= >= 和!=, 以 及 AND OR 与 括 号, 些 可 用 于 写 表 式 根 据 一 个 字 段 返 回 的 行 行 排 序 的 如 下 : SELECT title,plays FROM Tracks ORDER BY title 要 移 除 行, 需 要 在 SQL 的 DELETE 句 增 加 一 个 WHERE 子 句 WHERE 子 句 决 定 些 行 可 被 除 : DELETE FROM Tracks WHERE title = 'My Way' 在 一 个 表 中 可 以 用 SQL 的 UPDATE 句 一 行 或 多 行 的 一 个 列 或 多 列 行 更 新 UPDATE Tracks SET plays = 16 WHERE title = 'My Way' UPDATE 句 先 指 明 待 更 新 的 表, 在 SET 关 之 后 置 修 改 的 字 段 及 其 取, 然 后 可 以 用 WHERE 子 句 ( 可 的 ) 要 更 新 的 行 一 个 UPDATE 句 会 修 改 WHERE 子 句 匹 配 到 的 所 有 行, 若 不 指 定 WHERE 子 句, 它 将 更 新 表 中 所 有 的 行 以 上 是 数 据 建 与 的 四 个 基 本 SQL 命 令 (INSERT SELECT UPDATE 和 DELETE) 14.6 使 用 数 据 爬 取 Twitter 数 据 与 化 言 SQL 128

在 本 中, 我 写 一 个 的 爬 虫 程 序, 通 Twitter 号 采 集 数 据, 然 后 建 立 数 据 注 意 : 慎 行 个 程 序, 不 要 抓 取 太 多 数 据 或 行 程 序, 会 致 你 的 Twitter 号 被 封 任 何 型 的 爬 虫 程 序 都 面 一 个, 它 需 要 能 被 停 止 和 重 多 次, 你 也 不 想 失 已 取 到 的 数 据 你 不 希 望 是 在 一 开 始 重 数 据 索, 因 此 把 索 到 的 数 据 存 起 来, 爬 虫 程 序 能 份, 并 在 它 离 开 的 地 方 索 我 通 索 一 个 用 的 Twitter 朋 友 及 他 的 状, 循 朋 友 列 表, 向 数 据 添 加 每 个 朋 友 的 信 息, 以 后 索 当 理 了 一 个 用 的 Twitter 朋 友, 我 登 数 据, 索 朋 友 中 的 一 个 重 复 个 操 作, 挑 一 个 未 的 用, 索 他 的 用 列 表, 添 加 列 表 中 没 有 的 朋 友, 以 下 次 我 也 追 踪 数 据 中 特 定 朋 友 的 出 次 数, 以 此 看 人 气 情 况 通 存 已 知 号 的 列 表, 不 是 否 索 个 号, 数 据 中 号 的 人 气 情 况 已 存 在 算 机 磁, 停 止 或 重 程 序 多 少 次 都 没 关 系 个 程 序 有 些 复, 它 基 于 前 面 的 Twitter API 程 序 代 Twitter 爬 虫 程 序 源 代 如 下 : import urllib import twurl import json import sqlite3 TWITTER_URL = 'https://api.twitter.com/1.1/friends/list.json' conn = sqlite3.connect('spider.sqlite3') cur = conn.cursor() cur.execute("' CREATE TABLE IF NOT EXISTS Twitter (name TEXT, retrieved INTEGER, friends INTEGER)"') while True: acct = raw_input('enter a Twitter account, or quit: ') if ( acct == 'quit' ) : break if ( len(acct) < 1 ) : cur.execute('select name FROM Twitter WHERE retrieved = 0 LIMIT 1') try: acct = cur.fetchone()[0] except: print 'No unretrieved Twitter accounts found' continue url = twurl.augment(twitter_url, {'screen_name': acct, 'count': '20'} ) print 'Retrieving', url connection = urllib.urlopen(url) data = connection.read() headers = connection.info().dict # print 'Remaining', headers['x-rate-limit-remaining'] js = json.loads(data) # print json.dumps(js, indent=4) cur.execute('update Twitter SET retrieved=1 WHERE name =?', (acct, ) ) countnew = 0 countold = 0 for u in js['users'] : friend = u['screen_name'] print friend cur.execute('select friends FROM Twitter WHERE name =? LIMIT 1', (friend, ) ) try: count = cur.fetchone()[0] cur.execute('update Twitter SET friends =? WHERE name =?', (count+1, friend) ) countold = countold + 1 except: 数 据 与 化 言 SQL 129

cur.execute("'insert INTO Twitter (name, retrieved, friends) VALUES (?, 0, 1 )"', ( friend, ) ) countnew = countnew + 1 print 'New accounts=',countnew,' revisited=',countold conn.commit() cur.close() 数 据 存 在 于 spider.sqlite3 文 件 中, 包 括 一 个 Twitter 表 Twitter 表 的 每 一 行 包 括 号 名 是 否 索 个 号 的 朋 友 以 及 个 号 被 加 好 友 的 次 数 在 程 序 的 主 循 中, 提 示 用 入 一 个 Twitter 号 名 或 退 出 程 序 如 果 用 入 一 个 Twitter 号, 程 序 就 索 朋 友 列 表 和 用 状, 如 果 数 据 中 没 有 个 朋 友, 添 加 去 如 果 朋 友 已 存 在 于 列 表 中, 我 friends 字 段 加 一 当 用 按 下 回, 在 数 据 中 找 下 一 个 未 索 的 Twitter 号, 索 号 的 朋 友 与 状, 把 添 加 他 到 数 据, 或 更 新 它, 增 加 friends 字 段 的 当 取 到 朋 友 列 表 与 状, 我 返 回 的 JSON 中 所 有 的 user 数 据 行 循, 索 每 个 用 的 screen_name 然 后, 使 用 SELECT 句 screen_name 是 否 已 存 到 数 据 中 了 如 果 存 在 的, 索 朋 友 数 (friends 字 段 ) countnew = 0 countold = 0 for u in js['users'] : friend = u['screen_name'] print friend cur.execute('select friends FROM Twitter WHERE name =? LIMIT 1', (friend, ) ) try: count = cur.fetchone()[0] cur.execute('update Twitter SET friends =? WHERE name =?', (count+1, friend) ) countold = countold + 1 except: cur.execute("'insert INTO Twitter (name, retrieved, friends) VALUES (?, 0, 1 )"', ( friend, ) ) countnew = countnew + 1 print 'New accounts=',countnew,' revisited=',countold conn.commit() 当 游 行 SELECT 句, 我 必 索 表 的 行 用 for 句 来, 由 于 只 索 了 一 行 (LIMIT 1), 我 使 用 fetchone() 方 法 取 第 一 ( 也 是 唯 一 ) 行, 就 是 SELECT 操 作 的 果 由 于 fetchone() 以 元 返 回 行, 即 使 有 一 个 字 段 也 是 如 此 我 用 [0] 取 出 元 的 第 一 个, 得 到 量 count 的 当 前 朋 友 数 如 果 取 成 功, 我 使 用 SQL 的 UPDATE 句 和 WHERE 子 句, 匹 配 到 的 朋 友 号 所 在 行 的 friends 列 加 一 注 意, SQL 句 中 有 个 占 位 符 ( 即 号 ), execute() 的 第 二 个 参 数 是 元 素 元, 其 中 的 会 替 SQL 的 占 位 符 如 果 try 区 的 代 失 效, 可 能 是 因 SELECT 句 的 WHERE name =? 子 句 没 有 匹 配 到 在 except 区, 我 使 用 SQL 的 INSERT 句, 向 表 中 添 加 朋 友 的 screen_name, 外 一 个 指 示 符 表 示 我 没 有 取 到 screen_name, 将 朋 友 数 0 第 一 次 行 程 序, 入 一 个 Twitter 号, 程 序 行 果 如 下 : Enter a Twitter account, or quit: drchuck Retrieving http://api.twitter.com/1.1/friends... New accounts= 20 revisited= 0 Enter a Twitter account, or quit: quit 由 于 是 第 一 次 行 个 程 序, 数 据 是 空 的, 我 建 了 一 个 数 据 文 件 spider.sqlite3, 向 数 据 添 加 一 Twitter 表 然 后 取 一 些 朋 友, 将 他 的 信 息 存 到 之 前 空 的 数 据 中 数 据 与 化 言 SQL 130

此, 我 想 要 写 一 个 的 数 据 出 程 序, 用 来 看 spider.sqlites3 文 件 : import sqlite3 conn = sqlite3.connect('spider.sqlite3') cur = conn.cursor() cur.execute('select * FROM Twitter') count = 0 for row in cur : print row count = count + 1 print count, 'rows.' cur.close() 如 果 再 次 行 Twitter 爬 虫 程 序, 程 序 行 果 如 下 : (u'opencontent', 0, 1) (u'lhawthorn', 0, 1) (u'steve_coppin', 0, 1) (u'davidkocher', 0, 1) (u'hrheingold', 0, 1)... 20 rows. 我 看 到 每 个 screen_name 有 一 行, 没 有 取 字 段 本 身 的 数 据, 数 据 中 每 人 有 一 个 朋 友 在, 在 数 据 里 可 以 看 到 第 一 个 Twitter 号 (drchuck) 的 朋 友 已 取 到 我 再 次 行 个 程 序, 只 需 按 下 回, 不 用 再 入 Twitter 号, 程 序 就 会 索 下 一 个 未 理 号 的 朋 友 信 息 Enter a Twitter account, or quit: Retrieving http://api.twitter.com/1.1/friends... New accounts= 18 revisited= 2 Enter a Twitter account, or quit: Retrieving http://api.twitter.com/1.1/friends... New accounts= 17 revisited= 3 Enter a Twitter account, or quit: quit 由 于 我 按 下 了 回 ( 即 没 有 指 定 Twitter 号 ), 行 下 面 的 代 : if ( len(acct) < 1 ) : cur.execute('select name FROM Twitter WHERE retrieved = 0 LIMIT 1') try: acct = cur.fetchone()[0] except: print 'No unretrieved twitter accounts found' continue 我 使 用 SQL 的 SELECT 句 取 第 一 个 用 的 名 称 (LIMIT 1), 但 用 的 是 否 字 段 是 0 我 在 try/except 区 中 使 用 fetchone()[0] 模 式, 从 索 到 的 数 据 中 抽 取 screen_name, 或 是 得 到 一 个 消 息 和 循 份 如 果 成 功 取 到 一 个 未 理 的 screen_name, 索 数 据 的 程 序 代 如 下 : url = twurl.augment(twitter_url, {'screen_name': acct, 'count': '20'} ) print 'Retrieving', url connection = urllib.urlopen(url) data = connection.read() js = json.loads(data) cur.execute('update Twitter SET retrieved=1 WHERE name =?', (acct, ) ) 数 据 与 化 言 SQL 131

一 旦 成 功 取 数 据, 我 使 用 UPDATE 句 置 retrieved 列 1, 表 示 已 完 成 号 的 朋 友 索 保 了 不 会 重 复 索 相 同 的 数 据, 理 行, 最 形 成 Twitter 朋 友 网 如 果 我 行 friend 程 序, 按 次 回, 索 下 一 个 未 被 的 朋 友 的 朋 友, 然 后 行 dumping 程 序, 程 序 出 果 如 下 : (u'opencontent', 1, 1) (u'lhawthorn', 1, 1) (u'steve_coppin', 0, 1) (u'davidkocher', 0, 1) (u'hrheingold', 0, 1)... (u'cnxorg', 0, 2) (u'knoop', 0, 1) (u'kthanos', 0, 2) (u'lecturetools', 0, 1)... 55 rows. 由 此 可, 我 正 确 了 已 的 lhawthorn 和 opencontent 个 号 的 信 息 外,cnxorg 和 kthanos 已 有 了 粉 由 于 已 索 了 三 个 用 (drchuck opencontent 与 lhawthorn) 的 朋 友, 表 中 已 有 55 行 每 次 行 程 序 与 按 下 回, 它 会 下 一 个 未 的 号 ( 里 的 下 一 个 号 是 steve_coppin), 取 他 的 朋 友, 他, 循 steve_coppin 的 每 一 位 朋 友, 将 他 添 加 到 数 据 如 果 他 已 存 在 于 数 据, 更 新 他 的 朋 友 数 由 于 程 序 的 数 据 全 部 存 在 数 据 的 磁 上, 爬 虫 活 可 以 被 任 意 多 次 停 或, 数 据 都 不 会 失 14.7 基 数 据 建 模 关 系 型 数 据 的 真 正 力 在 于, 建 多 个 表 以 及 表 接 将 用 数 据 分 解 多 个 表 并 确 立 个 表 的 关 系, 一 程 称 数 据 建 模 示 表 与 表 关 系 的 文 档 称 数 据 模 型 数 据 建 模 是 相 复 的 技 能, 本 介 最 基 的 关 系 型 数 据 建 模 数 据 建 模 的 更 多, 以 下 基 面 : http://en.wikipedia.org/wiki/relational_model 我 来 看 Twitter 爬 虫 程 序, 不 一 个 用 的 朋 友 数, 我 希 望 得 到 所 有 的 入 关 系, 即 找 到 特 定 号 的 所 有 粉 的 列 表 由 于 每 个 人 都 可 能 会 有 多 粉, 所 以 不 能 添 加 一 列 到 Twitter 表 因 此, 我 新 建 一 个 表 来 跟 踪 朋 友 下 面 是 新 建 表 的 一 种 方 法 : CREATE TABLE Pals (from_friend TEXT, to_friend TEXT) 每 当 遇 到 drchuck 的 一 个 粉, 我 向 表 中 插 入 一 行 : INSERT INTO Pals (from_friend,to_friend) VALUES ('drchuck', 'lhawthorn') 当 理 了 drchuck 的 20 个 朋 友 的 Twitter 消 息 源 (feed), 我 插 入 drchuck 作 第 一 参 数 的 20 条, 个 字 符 串 在 数 据 重 复 出 了 多 次 重 复 的 字 符 串 数 据 破 坏 了 数 据 范 化 的 最 佳 践 数 据 范 化 指 相 同 的 字 符 串 数 据 在 数 据 只 能 存 在 一 如 果 需 要 数 据 出 多 次, 要 数 据 建 一 个 数 字, 通 引 用 的 数 据 在 用 中, 字 符 串 比 整 数 在 算 机 磁 与 内 存 上 占 用 更 多 空, 理 器 也 需 要 更 多 行 比 和 排 序 如 果 有 几 百 数 据 与 化 言 SQL 132

条 数 据, 那 么 存 与 理 器 耗 并 没 什 么 但 当 数 据 中 包 括 百 万 用, 以 及 可 能 的 一 朋 友 接, 尽 可 能 快 速 描 数 据 就 得 非 常 重 要 了 我 把 Twitter 号 存 在 People 表, 而 不 是 之 前 示 例 的 Twitter 表 People 表 用 外 的 一 列 来 存 与 Twitter 用 的 行 数 相 关 的 数 SQLite 的 INTEGER PRIMARY KEY 一 特 殊 的 数 据 列 型 能 插 入 的 任 一 行 自 增 加 新 建 People 表, 包 括 一 个 外 的 id 列 : CREATE TABLE People (id INTEGER PRIMARY KEY, name TEXT UNIQUE, retrieved INTEGER) 注 意, 我 不 再 People 表 每 一 行 的 朋 友 数 当 INTEGER PRIMARY KEY 作 id 列 的 字 段 型, 表 明 我 希 望 SQLite 来 管 理 列, 在 插 入 一 行 自 予 唯 一 的 数 我 添 加 了 关 UNIQUE, 表 示 不 允 SQLite 个 行 插 入 相 同 的 与 之 前 建 的 Pals 表 不 同, 我 建 了 一 个 Follows 表, 包 括 from_id 和 to_id 个 整 数 列, 以 及 一 个 表 束, 表 中 from_id 和 to_id 必 唯 一, 即 不 能 在 数 据 中 插 入 重 复 的 行 CREATE TABLE Follows (from_id INTEGER, to_id INTEGER, UNIQUE(from_id, to_id) ) 向 表 中 添 加 UNIQUE 子 句, 当 插 入, 我 要 求 数 据 强 制 行 一 套 在 程 序 中 建 些 的 方 便 性 稍 后 会 明 些 避 免 我 犯, 并 化 了 一 些 代 写 从 本 上,Follows 表 的 建 是 建 了 一 个 关 系, 一 个 用 是 其 他 人 的 粉, 将 其 表 示 成 一 个 数, 代 表 与 他 系 的 用, 以 及 关 系 的 方 向 14.8 多 表 程 我 使 用 之 前 的 个 表 主 和 引 用 来 重 做 Twitter 爬 虫 程 序 新 版 本 的 程 序 代 如 下 : import urllib import twurl import json import sqlite3 TWITTER_URL = 'https://api.twitter.com/1.1/friends/list.json' conn = sqlite3.connect('friends.sqlitesqlite3') 数 据 与 化 言 SQL 133

cur = conn.cursor() cur.execute("'create TABLE IF NOT EXISTS People (id INTEGER PRIMARY KEY, name TEXT UNIQUE, retrieved INTEGER)"') cur.execute("'create TABLE IF NOT EXISTS Follows (from_id INTEGER, to_id INTEGER, UNIQUE(from_id, to_id))"') while True: acct = raw_input('enter a Twitter account, or quit: ') if ( acct == 'quit' ) : break if ( len(acct) < 1 ) : cur.execute("'select id, name FROM People WHERE retrieved = 0 LIMIT 1"') try: (id, acct) = cur.fetchone() except: print 'No unretrieved Twitter accounts found' continue else: cur.execute('select id FROM People WHERE name =? LIMIT 1', (acct, ) ) try: id = cur.fetchone()[0] except: cur.execute("'insert OR IGNORE INTO People (name, retrieved) VALUES (?, 0)"', ( acct, ) ) conn.commit() if cur.rowcount!= 1 : print 'Error inserting account:',acct continue id = cur.lastrowid url = twurl.augment(twitter_url, {'screen_name': acct, 'count': '20'} ) print 'Retrieving account', acct connection = urllib.urlopen(url) data = connection.read() headers = connection.info().dict print 'Remaining', headers['x-rate-limit-remaining'] js = json.loads(data) # print json.dumps(js, indent=4) cur.execute('update People SET retrieved=1 WHERE name =?', (acct, ) ) countnew = 0 countold = 0 for u in js['users'] : friend = u['screen_name'] print friend cur.execute('select id FROM People WHERE name =? LIMIT 1', (friend, ) ) try: friend_id = cur.fetchone()[0] countold = countold + 1 except: cur.execute("'insert OR IGNORE INTO People (name, retrieved) VALUES (?, 0)"', ( friend, ) ) conn.commit() if cur.rowcount!= 1 : print 'Error inserting account:',friend continue friend_id = cur.lastrowid countnew = countnew + 1 cur.execute("'insert OR IGNORE INTO Follows (from_id, to_id) VALUES (?,?)"', (id, friend_id) ) print 'New accounts=',countnew,' revisited=',countold conn.commit() cur.close() 个 程 序 得 有 些 复 了, 介 了 通 整 数 接 表 格 的 使 用 模 式 基 本 模 式 如 下 : 1. 建 有 主 与 束 的 表 2. 当 一 个 用 ( 即 号 名 称 ) 有 一 个, 我 需 要 用 的 id 根 据 People 表 中 是 否 有 用,(1) 找 People 表 数 据 与 化 言 SQL 134

中 的 用, 取 用 的 id, 或 (2) 向 People 表 添 加 用, 新 增 行 添 加 id 3. 插 入 一 行, 表 示 粉 关 系 以 下 依 次 介 每 一 个 步 14.8.1 数 据 表 束 表, 我 告 数 据 系 强 制 行 一 些 些 帮 助 我 避 免 出, 不 要 把 的 数 据 写 入 表 中 建 表 的 代 如 下 : cur.execute("'create TABLE IF NOT EXISTS People (id INTEGER PRIMARY KEY, name TEXT UNIQUE, retrieved INTEGER)"') cur.execute("'create TABLE IF NOT EXISTS Follows (from_id INTEGER, to_id INTEGER, UNIQUE(from_id, to_id))"') 我 定 People 表 中 的 name 列 必 是 唯 一 的 (UNIQUE) 同, 定 Follows 表 每 一 行 个 数 字 的 合 必 唯 一 些 束 避 免 了 多 次 添 加 同 一 个 关 系 以 下 代 体 了 些 束 的 : cur.execute("'insert OR IGNORE INTO People (name, retrieved) VALUES (?, 0)"', ( friend, ) ) 我 在 INSERT 句 中 添 加 OR IGNORE 子 句, 表 示 如 果 有 一 个 INSERT 反 了 name 必 唯 一 的, 那 么 数 据 将 忽 略 个 INSERT 数 据 束 作 一 个 安 全 网, 确 保 我 不 会 在 无 意 中 犯 同 地, 以 下 代 确 保 不 会 重 复 添 加 同 一 个 Follows 关 系 cur.execute("'insert OR IGNORE INTO Follows (from_id, to_id) VALUES (?,?)"', (id, friend_id) ) 同 地, 如 果 反 了 Follows 行 的 唯 一 性 束, 只 需 告 数 据 忽 略 INSERT 即 可 14.8.2 索 与 插 入 一 条 当 提 示 用 入 一 个 Twitter 号, 如 果 号 已 存 在, 我 必 找 到 它 的 id 如 果 People 表 中 没 有 号, 我 必 插 入 一 条, 并 得 到 插 入 行 的 id 是 一 个 很 常 的 模 式, 在 前 面 的 程 序 中 用 到 2 次 当 我 从 已 取 的 Twitter 的 JSON 数 据 中 取 user 点 的 screen_name, 本 代 演 示 了 如 何 索 一 个 朋 友 号 的 id 随 着 数 据 的 累, 用 号 可 能 已 存 在 于 数 据 中 我 需 要 先 使 用 SELECT 句, People 表 中 号 是 或 否 存 在 如 果 try 部 分 一 切 展 利 2, 我 使 用 fetchone() 取, 然 后 索 返 回 的 元 的 第 一 个 ( 也 是 唯 一 ) 元 素, 将 其 存 friend_id 如 果 SELECT 行 失,fetchone()[0] 也 会 失, 然 后 控 制 跳 到 except 部 分 friend = u['screen_name'] cur.execute('select id FROM People WHERE name =? LIMIT 1', (friend, ) ) try: friend_id = cur.fetchone()[0] countold = countold + 1 数 据 与 化 言 SQL 135

except: cur.execute("'insert OR IGNORE INTO People (name, retrieved) VALUES (?, 0)"', ( friend, ) ) conn.commit() if cur.rowcount!= 1 : print 'Error inserting account:',friend continue friend_id = cur.lastrowid countnew = countnew + 1 如 果 以 except 代 束, 意 味 着, 没 有, 必 插 入 新 行 我 使 用 INSERT OR IGNORE 是 避 免 出, 然 后 用 commit() 来 强 制 数 据 提 交 行 更 新 当 写 入 完 成 后, 我 通 cur.rowcount 有 多 少 行 受 到 影 由 于 我 插 入 一 个 行, 如 果 受 影 行 的 数 字 不 是 1, 那 么 将 致 如 果 INSERT 行 成 功, 我 通 cur.lastrowid 找 出 数 据 新 建 行 予 的 id 列 14.8.3 存 朋 友 关 系 一 旦 知 道 了 JSON 数 据 中 Twitter 用 与 朋 友 的, 在 Follows 表 中 插 入 个 就 是 件 的 事 情 了, 程 序 代 如 下 : cur.execute('insert OR IGNORE INTO Follows (from_id, to_id) VALUES (?,?)', (id, friend_id) ) 注 意, 根 据 表 格 建 的 唯 一 性 束, 避 免 了 重 复 插 入 同 一 个 关 系, 然 后 在 INSERT 句 中 添 加 OR IGNORE 程 序 行 果 如 下 所 示 : Enter a Twitter account, or quit: No unretrieved Twitter accounts found Enter a Twitter account, or quit: drchuck Retrieving http://api.twitter.com/1.1/friends... New accounts= 20 revisited= 0 Enter a Twitter account, or quit: Retrieving http://api.twitter.com/1.1/friends... New accounts= 17 revisited= 3 Enter a Twitter account, or quit: Retrieving http://api.twitter.com/1.1/friends... New accounts= 17 revisited= 3 Enter a Twitter account, or quit: quit 从 drchuck 号 开 始, 程 序 自 取 下 个 号, 并 添 加 到 数 据 当 程 序 行 完 成 后, 以 下 是 People 和 Follows 表 的 几 行 : People: (1, u'drchuck', 1) (2, u'opencontent', 1) (3, u'lhawthorn', 1) (4, u'steve_coppin', 0) (5, u'davidkocher', 0) 55 rows. Follows: (1, 2) (1, 3) (1, 4) (1, 5) (1, 6) 60 rows. 可 以 看 出,People 表 中 的 id name 与 visited 字 段, 关 系 Follows 表 尾 的 数 字 在 People 表 中, 我 看 到 前 三 个 用 已 被 数 据 与 化 言 SQL 136

, 他 的 数 据 已 被 取 Follows 表 的 数 据 表 明,drchuck( 用 1) 是 所 示 前 五 行 的 用 的 朋 友 是 由 于 我 取 和 存 的 第 一 个 数 据 是 drchuck 的 Twitter 朋 友 如 果 打 印 出 Follows 表 的 更 多 行, 就 会 看 到 用 2 和 用 3 的 朋 友 14.9 的 三 种 型 在 我 已 开 始 建 数 据 模 型 了, 将 数 据 放 入 多 个 关 表 中, 使 用 来 接 些 表 中 的 行 我 需 要 知 道 一 些 有 关 的 数 据 模 型 中 一 般 存 在 三 种 型 的 是 真 世 界 中 可 以 索 行 的 在 示 例 数 据 模 型 中,name 字 段 是 一 个 它 是 用 的 屏 幕 名 称, 在 程 序 中 通 name 字 段 多 次 索 用 的 行 你 会, 一 个 添 加 UNIQUE 束, 是 有 道 理 的 由 于 是 我 从 外 部 世 界 如 何 索 表 中 的 一 行, 允 表 中 存 在 相 同 的 多 行 没 有 多 大 意 主 通 常 是 由 数 据 自 予 的 一 个 数 字 它 外 部 程 序 而 言 没 有 意, 用 于 把 来 自 不 同 表 的 行 接 在 一 起 当 我 索 表 中 的 行, 通 常 搜 索 主 是 最 快 的 由 于 主 是 整 数, 占 用 极 少 的 存 空, 能 快 速 行 比 与 排 序 在 示 例 数 据 模 型 中,id 字 段 是 主 外 通 常 是 指 向 不 同 表 中 相 关 行 的 主 的 一 个 数 示 例 数 据 模 型 中 的 外 是 from_id 我 使 用 一 些 命 名 例, 比 如 主 名 id, 那 么 将 _id 后 添 加 到 外 的 名 称 中 14.10 使 用 JSON 取 数 据 我 已 了 解 了 数 据 范 化 原, 将 数 据 分 成 个 表, 通 主 和 外 将 个 表 接 起 来, 然 后 通 SELECT 将 跨 表 格 的 数 据 装 在 一 起 SQL 使 用 接 (JOIN) 子 句 把 表 重 新 接 在 JOIN 子 句 中 可 以 指 定 用 以 接 表 之 行 的 字 段 下 面 是 有 JOIN 子 句 的 SELECT 句 示 例 : SELECT * FROM Follows JOIN People ON Follows.from_id = People.id WHERE People.id = 1 JOIN 子 句 表 示, 从 Follows 与 People 个 表 中 所 有 字 段 ON 子 句 表 示, 个 表 怎 被 接 在 一 起 取 People 表 的 行, 然 后 将 Follows 表 的 from_id 字 段 与 People 表 的 id 字 段 相 同 的 行 附 加 在 后 面 接 的 果 是 建 了 一 个 相 当 的 元 行 (meta-rows), 包 括 People 表 的 字 段 与 Follows 表 中 匹 配 的 字 段 由 于 People 表 的 id 字 段 与 Follows 表 中 的 from_id 字 段 之 存 在 多 个 匹 配,JOIN 会 每 一 个 匹 配 到 的 行 建 一 个 元 行, 根 据 需 要 重 复 数 据 数 据 与 化 言 SQL 137

多 表 数 据 的 Twitter 爬 虫 程 序 多 次 行 的 代 如 下 : import sqlite3 conn = sqlite3.connect('spider.sqlite3') cur = conn.cursor() cur.execute('select * FROM People') count = 0 print 'People:' for row in cur : if count < 5: print row count = count + 1 print count, 'rows.' cur.execute('select * FROM Follows') count = 0 print 'Follows:' for row in cur : if count < 5: print row count = count + 1 print count, 'rows.' cur.execute("'select * FROM Follows JOIN People ON Follows.from_id = People.id WHERE People.id = 2"') count = 0 print 'Connections for id=2:' for row in cur : if count < 5: print row count = count + 1 print count, 'rows.' cur.close() 在 个 程 序 中, 我 首 先 整 体 出 People 与 Follows 表, 然 后 出 接 表 的 数 据 子 集 程 序 出 果 如 下 : python twjoin.py People: (1, u'drchuck', 1) (2, u'opencontent', 1) (3, u'lhawthorn', 1) (4, u'steve_coppin', 0) (5, u'davidkocher', 0) 55 rows. Follows: (1, 2) (1, 3) (1, 4) (1, 5) (1, 6) 60 rows. Connections for id=2: (2, 1, 1, u'drchuck', 1) (2, 28, 28, u'cnxorg', 0) (2, 30, 30, u'kthanos', 0) (2, 102, 102, u'somethinggirl', 0) (2, 103, 103, u'ja_pac', 0) 20 rows. 可 以 看 出,People 与 Follows 表 的 列 和 JOIN 子 句 的 SELECT 句 行 后 得 到 的 果 行 最 后 一 次 中 我 找 到 opencontent ( 即 People.id=2) 的 朋 友 号 在 最 后 一 次 的 每 个 元 行 中, 前 列 来 自 Follows 表, 之 后 是 People 表 5 个 列 中 的 3 个 接 后 的 每 个 元 行 中 第 2 列 (Follows.to_id) 匹 配 第 3 列 (People.id) 数 据 与 化 言 SQL 138

14.11 小 本 章 全 面 介 了 Python 中 数 据 的 基 本 使 用 方 法 与 Python 字 典 或 平 面 文 件 相 比, 写 代 来 使 用 数 据 存 数 据 更 加 复 除 非 你 的 用 程 序 确 需 要 数 据 功 能, 否 不 要 易 使 用 数 据 的 使 用 在 于 :(1) 用 程 序 需 要 在 大 量 数 据 中 随 机 更 新 一 小 部 分 数 据 ;(2) 数 据 量 很 大, 无 法 用 字 典 来 存, 而 且 需 要 重 复 索 信 息 ;(3) 在 期 行 程 中 希 望 停 止 或 重, 数 据 可 以 得 以 保 留, 并 在 下 次 行 从 中 止 你 可 以 建 表 的 数 据, 以 足 多 种 用 需 求 但 是, 大 多 数 都 需 要 多 个 表 与 跨 表 的 行 之 的 接 / 关 系 表 建 接, 需 要 行 周 全, 遵 循 数 据 范 化 原, 恰 当 地 用 数 据 能 力 数 据 的 使 用 机 主 要 需 要 理 大 量 数 据, 有 效 的 数 据 建 模 程 序 能 快 速 行, 把 握 住 一 点 很 重 要 14.12 一 个 常 的 Python 程 序 开 模 式 是 与 SQLite 数 据 建 立 系, 行 Python 程 序, 使 用 SQLite 数 据 器 看 果 个 器 可 以 快 速 程 序 是 否 正 常 行 由 于 SQLite 在 同 一 刻 会 防 止 个 程 序 同 一 数 据 的 修 改 例 如, 如 果 在 器 中 打 开 数 据, 修 改 数 据, 在 尚 未 按 下 保 存 按, 器 会 定 数 据 文 件, 以 防 止 其 他 程 序 文 件 具 体 而 言, 如 果 数 据 文 件 被 定, 你 的 Python 程 序 将 不 能 个 文 件 一 个 解 决 方 法 是, 在 Python 数 据 之 前, 关 数 据 器 或 使 用 器 的 文 件 菜 来 关 数 据 可 以 避 免 数 据 定 致 的 Python 代 行 失 14.13 属 性 : 元 的 一 个 更 常 的 提 法 是 列 或 字 段 束 : 告 知 数 据 在 表 中 的 字 段 或 行 上 行 一 个 常 的 束 是 保 特 定 字 段 上 无 重 复 ( 即 所 有 必 唯 一 ) 游 : 行 数 据 的 SQL 命 令, 并 从 数 据 中 取 数 据 游 似 于 网 接 中 的 套 接 字 或 文 件 取 的 文 件 句 柄 数 据 器 : 一 种 无 需 写 程 序, 直 接 与 数 据 接 并 行 操 作 的 件 外 : 指 向 一 个 表 中 行 的 主 的 数 外 建 立 了 不 同 表 中 行 之 的 关 系 索 引 : 向 表 中 插 入 行, 数 据 件 由 于 需 要 而 生 的 外 数 据, 目 的 是 提 高 速 度 : 外 部 世 界 用 来 索 特 定 行 的 例 如, 在 用 信 息 表 中 用 的 子 件 地 址 是 不 的 用 数 据 候 范 化 : 数 据 模 型 要 保 无 重 复 的 数 据 每 个 数 据 只 存 在 数 据 的 一 个 位 置, 其 他 地 方 用 外 来 引 用 主 : 每 一 行 指 定 的 数, 用 于 当 前 表 中 的 行 与 一 个 表 中 的 行 之 建 立 引 用 关 系 数 据 的 默 配 置 会 自 插 入 的 行 予 主 关 系 : 数 据 中 包 含 元 与 属 性 的 一 区 域 更 典 型 的 提 法 是 表 元 : 数 据 中 表 的 一 个 数 据 条 目, 包 含 一 属 性 更 典 型 的 提 法 是 行 1. 上,SQLite 在 列 中 存 的 数 据 型 具 一 定 灵 活 性, 但 本 章 中 格 定 数 据 型, 做 些 概 念 也 能 适 用 于 其 他 数 据 系 ( 如 MySQL) 2. 一 般 来, 以 如 果 一 切 利 开 的, 你 会 需 要 使 用 try/except 数 据 与 化 言 SQL 139

第 15 章 数 据 可 化 至 此, 我 了 Python 言, 学 了 Python 的 基 本 用 法 网 接, 以 及 使 用 数 据 操 作 数 据 等 知 本 章 介 三 个 完 整 的 用 程 序, 将 之 前 学 到 的 知 整 合 起 来, 数 据 行 管 理 与 可 化 你 可 以 使 用 些 程 序 代 来 解 决 每 个 用 程 序 是 一 个 ZIP 文 件, 可 以 下 和 解 到 本 地 算 机 上 行 15.1 根 据 地 理 数 据 建 Google 地 用 个 目 使 用 Google 的 地 理 API 来 清 洗 用 入 的 大 学 地 名, 然 后 将 些 数 据 示 在 Google 地 上 从 以 下 地 址 下 用 程 序 : http://www.py4inf.com/code/geodata.zip 首 先 要 解 决 的 是, 免 的 Google 地 理 API 每 天 的 求 数 量 有 一 定 限 制 如 果 数 据 多, 可 能 需 要 在 程 中 多 次 停 止 与 重 里, 我 把 分 解 成 个 段 第 一 段, 按 行 入 where.data 文 件 中 的 数 据, 通 Google 取 地 理 信 息, 将 其 存 在 geodata.sqlite 数 据 在 每 个 用 入 的 地 名 使 用 地 理 API 之 前, 我 需 要 下 入 的 行 是 否 有 数 据 存 在 数 据 具 有 本 地 存 功 能, 可 以 地 理 数 据 行 存, 就 无 需 向 Google 重 复 求 同 一 数 据 移 除 geodata.sqlite 文 件 之 后, 你 可 以 任 何 候 重 个 程 行 geoload.py 程 序, 依 次 入 where.data 文 件 的 每 一 行, 数 据 在 数 据 是 否 存 在 若 不 存 在, 用 地 理 API 取 数 据, 将 其 存 在 数 据 中 下 面 是 数 据 已 有 一 些 数 据 的 情 况, 程 序 行 果 如 下 : Found in database Northeastern University Found in database University of Hong Kong,... Found in database Technion Found in database Viswakarma Institute, Pune, India Found in database UMD Found in database Tufts University Resolving Monash University Retrieving http://maps.googleapis.com/maps/api/ geocode/json?sensor=false&address=monash+university Retrieved 2063 characters { "results" : [ {u'status': u'ok', u'results':... } 数 据 可 化 140

Resolving Kokshetau Institute of Economics and Management Retrieving http://maps.googleapis.com/maps/api/ geocode/json?sensor=false&address=kokshetau+inst... Retrieved 1749 characters { "results" : [ {u'status': u'ok', u'results':... }... 前 5 个 地 名 已 存 在 于 数 据 中, 所 以 它 被 跳 程 序 会 描 到 未 索 的 地 名, 然 后 开 始 取 数 据 geoload.py 可 以 随 停 止, 有 一 个 数 器 用 来 控 制 每 次 行 中 地 理 API 的 用 上 限 由 于 where.data 只 包 括 几 百 个 数 据, 所 以 无 需 置 日 限 制 如 果 数 据 量 很 大, 需 要 几 天 的 多 次 行 才 能 取 所 有 的 地 理 数 据, 种 情 况 下 就 需 要 置 限 制 了 入 一 些 数 据 到 geodata.sqlite 之 后, 你 可 以 使 用 geodump.py 程 序 数 据 行 可 化 此 程 序 会 取 数 据, 将 地 名 度 度 成 可 行 的 JavaScript 代 形 式, 写 入 where.js 文 件 geodump.py 行 果 如 下 : Northeastern University,... Boston, MA 02115, USA 42.3396998-71.08975 Bradley University, 1501... Peoria, IL 61625, USA 40.6963857-89.6160811... Technion, Viazman 87, Kesalsaba, 32000, Israel 32.7775 35.0216667 Monash University Clayton... VIC 3800, Australia -37.9152113 145.134682 Kokshetau, Kazakhstan 53.2833333 69.3833333... 12 records written to where.js Open where.html to view the data in a browser where.html 文 件 包 含 了 Google 地 可 化 所 需 的 HTML 与 JavaScript 代 它 入 where.js 文 件 中 的 最 新 数 据, 将 其 可 化 where.js 文 件 格 式 如 下 : mydata = [ [42.3396998,-71.08975, 'Northeastern Uni... Boston, MA 02115'], [40.6963857,-89.6160811, 'Bradley University,... Peoria, IL 61625, USA'], [32.7775,35.0216667, 'Technion, Viazman 87, Kesalsaba, 32000, Israel'],... ]; 个 JavaScript 量 是 一 个 包 含 列 表 的 列 表 JavaScript 列 表 常 量 的 法 与 Python 非 常 相 似, 你 不 会 感 到 陌 生 在 器 中 打 开 where.html 来 看 地 鼠 浮 在 地 点 上 可 以 看 到 地 理 API 的 用 入 的 地 名 如 果 打 开 where.html 文 件 看 不 到 数 据, 你 可 能 需 要 器 的 JavaScript 或 在 开 者 控 制 台 行 排 15.2 网 与 互 可 化 个 用 程 序 了 搜 索 引 擎 的 一 些 功 能 首 先, 爬 取 一 部 分 网 集 合, 然 后 了 一 个 Google 的 PageRank 算 法 化 版, 确 定 些 面 具 有 高 接 度, 最 后, 在 个 小 网 中 面 等 与 接 度 行 可 化 下 和 解 个 用 程 序 : http://www.py4inf.com/code/pagerank.zip 数 据 可 化 141

首 先,spider.py 程 序 爬 取 一 个 网 站, 将 网 站 的 面 存 到 spider.sqlite 数 据, 面 之 的 接 移 除 spider.sqlite 文 件 之 后, 你 可 以 随 再 次 行 spider.py Enter web url or enter: http://www.dr-chuck.com/ ['http://www.dr-chuck.com'] How many pages:2 1 http://www.dr-chuck.com/ 12 2 http://www.dr-chuck.com/csev-blog/ 57 How many pages: 在 程 序 行 中, 我 告 知 它 爬 取 一 个 网 站, 索 个 面 如 果 你 重 程 序, 可 以 它 爬 取 更 多 面, 它 不 会 重 复 爬 取 数 据 已 有 的 面 程 序 重 会 随 机 索 未 爬 取 的 面, 然 后 从 那 里 开 始 因 此,spider.py 程 序 的 每 一 次 行 都 是 累 式 的 Enter web url or enter: http://www.dr-chuck.com/ ['http://www.dr-chuck.com'] How many pages:3 3 http://www.dr-chuck.com/csev-blog 57 4 http://www.dr-chuck.com/dr-chuck/resume/speaking.htm 1 5 http://www.dr-chuck.com/dr-chuck/resume/index.htm 13 How many pages: 同 一 个 数 据 中 可 以 有 多 个 起 点, 在 程 序 中 称 网 爬 虫 程 序 随 机 网 中 未 的 接, 作 下 一 个 网 行 爬 取 如 果 要 出 spider.sqlite 文 件 内 容,spdump.py 程 序 行 果 如 下 : (5, None, 1.0, 3, u'http://www.dr-chuck.com/csev-blog') (3, None, 1.0, 4, u'http://www.dr-chuck.com/dr-chuck/resume/speaking.htm') (1, None, 1.0, 2, u'http://www.dr-chuck.com/csev-blog/') (1, None, 1.0, 5, u'http://www.dr-chuck.com/dr-chuck/resume/index.htm') 4 rows. 以 上 示 了 入 的 数 目 旧 的 面 排 名 新 的 面 排 名 面 id 和 面 的 url spdumpy 程 序 只 示 至 少 有 一 个 入 的 面 当 数 据 里 已 保 留 一 些 面 数 据 之 后, 行 sprank.py 程 序 来 面 排 名 你 只 需 指 定 面 排 名 的 迭 代 次 数 即 可 How many iterations:2 1 0.546848992536 2 0.226714939664 [(1, 0.559), (2, 0.659), (3, 0.985), (4, 2.135), (5, 0.659)] 再 次 出 数 据, 看 面 排 名 的 更 新 情 况 : 数 据 可 化 142

(5, 1.0, 0.985, 3, u'http://www.dr-chuck.com/csev-blog') (3, 1.0, 2.135, 4, u'http://www.dr-chuck.com/dr-chuck/resume/speaking.htm') (1, 1.0, 0.659, 2, u'http://www.dr-chuck.com/csev-blog/') (1, 1.0, 0.659, 5, u'http://www.dr-chuck.com/dr-chuck/resume/index.htm') 4 rows. sprank.py 可 以 行 多 次, 它 会 在 每 次 行 化 面 排 名 你 可 以 行 几 次 sprank.py, 然 后 用 spider.py 爬 取 一 些 面, 再 行 sprank.py 来 收 网 排 名 搜 索 引 擎 一 般 会 同 行 爬 取 程 序 与 排 名 程 序 如 果 在 没 有 重 新 爬 取 网 的 情 况 下 再 次 算 网 排 名, 你 可 以 用 sprest.py 程 序 重 置, 然 后 重 sprank.py How many iterations:50 1 0.546848992536 2 0.226714939664 3 0.0659516187242 4 0.0244199333 5 0.0102096489546 6 0.00610244329379... 42 0.000109076928206 43 9.91987599002e-05 44 9.02151706798e-05 45 8.20451504471e-05 46 7.46150183837e-05 47 6.7857770908e-05 48 6.17124694224e-05 49 5.61236959327e-05 50 5.10410499467e-05 [(512, 0.0296), (1, 12.79), (2, 28.93), (3, 6.808), (4, 13.46)] 于 PageRank 算 法 的 每 次 迭 代, 它 会 打 印 出 每 个 面 排 名 的 平 均 化 网 在 初 始 状 非 常 不 均 衡, 是 由 于 个 面 排 名 在 迭 代 程 中 化 很 大 一 些 迭 代 之 后, 面 排 名 开 始 收 了 行 prank.py 足 之 后, 网 排 名 就 会 相 定 如 果 想 要 网 排 名 中 当 前 靠 前 的 面 行 可 化, 行 spjson.py 程 序, 取 数 据, 将 最 高 接 面 的 数 据 JSON 格 式, 可 以 在 网 器 中 看 效 果 Creating JSON output on spider.json... How many nodes? 30 Open force.html in a browser to view the visualization 在 网 器 中 打 开 force.html 来 看 此 数 据 是 一 个 自 布 局 的 包 含 点 与 接 的 网 你 可 以 点 和 拖 拽 任 一 点, 也 可 以 双 点, 看 点 的 URL 如 果 重 新 行 其 他 工 具, 重 新 行 spjson.py, 在 器 中 点 刷 新, 示 spider.json 得 到 的 新 数 据 15.3 件 数 据 可 化 到 里, 你 得 mbox-short.txt 与 mbox.txt 个 数 据 文 件 下 面 我 将 深 入 分 析 些 子 件 数 据 在 世 界 中, 有 你 需 要 从 服 器 下 件 数 据, 可 能 要 花 相 当, 数 据 可 能 会 存 在 不 一 致, 充 和 需 要 做 大 量 清 洗 与 整 工 作 本 介 的 程 序 是 截 至 目 前 最 复 的, 从 服 器 下 近 1 个 G 大 小 的 数 据, 然 后 其 可 化 数 据 可 化 143

下 用 程 序 代 : http://www.py4inf.com/code/gmane.zip 里 使 用 http://www.gmane.org 的 免 子 件 列 表 档 服 由 于 服 提 供 了 子 件 活 的 档, 数 据 量 高 且 可 搜 索, 所 以 在 开 源 目 中 非 常 流 行 它 的 数 据 API 政 策 也 比 松, 没 有 限 制, 但 不 要 度 使 用, 取 你 需 要 的 数 据 即 可 你 可 以 在 下 面 的 网 中 gmane 的 条 款 与 条 件 : http://gmane.org/export.php 使 用 gmane.org 数 据 需 要 考, 在 服 和 行 任, 有 添 加 延, 一 点 非 常 重 要 不 要 用 免 服, 避 免 累 及 他 人 使 用 件 爬 取 Sakai 子 件 数 据, 可 能 会 生 1 个 G 的 数 据, 行 需 要 花 几 天 下 的 包 里 有 一 个 README.txt 文 件, 提 供 如 何 下 一 个 已 爬 取 的 content.sqlite 副 本 的 操 作 指 南, 无 需 花 5 天 行 程 序 来 爬 取 数 据 contet.sqlite 包 含 了 主 要 的 Sakai 子 件 料 如 果 下 了 先 爬 行 好 的 内 容, 你 仍 然 可 以 行 个 爬 取 程, 以 取 最 新 的 消 息 第 一 步 是 爬 取 gmane 档 在 gmane.py 中 基 URL 是 硬 的, 被 硬 Sakai 开 者 列 表 通 修 改 基 URL 可 以 爬 取 其 他 档 如 果 修 改 了 基 URL, 确 保 除 content.sqlite 文 件 gmane.py 文 件 作 一 个 任 的 存 型 爬 虫, 有 条 不 紊 行, 每 秒 索 一 条 件 信 息, 避 免 被 gmane 封 掉 它 把 所 有 数 据 存 在 数 据, 根 据 需 要 可 以 多 次 中 断 和 重 数 据 下 可 能 需 要 花 几 个 小 因 此, 程 序 行 中 可 能 需 要 重 几 次 gmane.py 程 序 取 到 Sakai 开 者 列 表 最 后 5 条 消 息 如 下 所 示 : How many messages:10 http://download.gmane.org/gmane.comp.cms.sakai.devel/51410/51411 9460 nealcaidin@sakaifoundation.org 2013-04-05 re: [building... http://download.gmane.org/gmane.comp.cms.sakai.devel/51411/51412 3379 samuelgutierrezjimenez@gmail.com 2013-04-06 re: [building... http://download.gmane.org/gmane.comp.cms.sakai.devel/51412/51413 9903 da1@vt.edu 2013-04-05 [building sakai] melete 2.9 oracle... http://download.gmane.org/gmane.comp.cms.sakai.devel/51413/51414 349265 m.shedid@elraed-it.com 2013-04-07 [building sakai]... http://download.gmane.org/gmane.comp.cms.sakai.devel/51414/51415 3481 samuelgutierrezjimenez@gmail.com 2013-04-07 re:... http://download.gmane.org/gmane.comp.cms.sakai.devel/51415/51416 0 Does not start with From 数 据 可 化 144

程 序 描 content.sqlite, 从 1 开 始, 直 到 找 到 未 被 爬 取 的 消 息 的 序 号, 然 后 开 始 爬 取 那 条 消 息 直 到 爬 取 到 需 要 的 消 息 序 号 或 者 到 一 个 不 符 合 消 息 格 式 的 面, 程 序 止 有 候,gmane.org 的 消 息 可 能 不 全, 可 能 是 管 理 被 除 了 或 消 息 被 弄 了 如 果 爬 虫 停 止, 可 能 是 它 碰 到 一 条 失 的 消 息 打 开 SQLite 管 理 器, 添 加 一 个 失 的 id, 其 他 字 段 留 空, 然 后 重 gmane.py 爬 取 程 就 可 以 了 些 空 消 息 在 下 段 理 会 被 忽 略 一 旦 爬 取 了 所 有 消 息 并 将 它 存 在 content.sqlite, 你 可 以 再 次 行 gmane.py 来 取 件 列 表 上 新 布 的 消 息 听 来 不 content.sqlite 的 数 据 缺 乏 有 效 的 数 据 模 型 和 未 被, 得 相 当 原 始 做 是 有 意 的, 它 可 以 你 在 SQLite 管 理 器 中 看 content.sqlite, 在 爬 取 程 中 如 果 想 要 个 数 据 行, 可 不 是 个 好 主 意, 效 率 会 非 常 低 第 二 段 是 行 gmodel.py 程 序 程 序 从 content.sqlite 入 原 始 数 据, 行 数 据 清 理 与 建 模, 生 成 index.sqlite 文 件 由 于 了 和 正 文,index.sqlite 比 content.sqlite 文 件 体 一 般 要 小 十 倍 每 次 行 gmodel.py, 它 都 会 除 和 重 建 index.sqlite, 允 整 参 数 和 content.sqlite 里 的 映 射 表, 从 而 控 制 数 据 清 洗 程 以 下 是 gmodel.py 的 行 情 况 示 例 每 理 250 条 件 消 息 之 后 打 印 一 行, 可 以 察 到 一 些 程 序 行 情 况 程 序 会 行 一 段, 期 理 近 1 个 G 的 子 件 数 据 Loaded allsenders 1588 and mapping 28 dns mapping 1 1 2005-12-08T23:34:30-06:00 ggolden22@mac.com 251 2005-12-22T10:03:20-08:00 tpamsler@ucdavis.edu 501 2006-01-12T11:17:34-05:00 lance@indiana.edu 751 2006-01-24T11:13:28-08:00 vrajgopalan@ucmerced.edu... gmodel.py 程 序 主 要 是 行 一 些 数 据 清 理 任 域 名.com.org.edu 和.net 被 截 断 成 2, 其 他 域 名 被 分 3 因 此,si.umich.edu 理 umich.edu,caret.cam.ac.uk 理 cam.ac.uk 外, 子 件 地 址 全 部 小 写 一 些 @gmane.org 地 址, 如 下 所 示 : arwhyte-63axycvo3tyhxe+lvdladg@public.gmane.org 的 件 地 址 如 果 与 料 中 的 真 子 件 地 址 匹 配, 就 会 被 真 地 址 content.sqlite 数 据 包 括 个 表, 允 域 名 与 个 人 子 件 ( 可 能 会 生 化 ) 之 行 映 射 例 如, 在 Sakai 开 者 列 表 中,Steve Githens 由 于 更 了 工 作, 使 用 以 下 子 件 地 址 : s-githens@northwestern.edu sgithens@cam.ac.uk swgithen@mtu.edu 我 在 contente.sqlite 的 Mapping 表 中 添 加 条 数 据, gmodel.py 就 可 以 将 3 个 子 件 地 址 映 射 一 个 地 址 : s-githens@northwestern.edu -> swgithen@mtu.edu sgithens@cam.ac.uk -> swgithen@mtu.edu 如 果 多 个 DNS 名 需 要 映 射 到 一 个 DNS 上, 你 也 可 以 在 DNSMapping 表 中 做 似 添 加 如 下 映 射 添 加 到 Sakai 数 据 中 : iupui.edu -> indiana.edu 数 据 可 化 145

, 所 有 印 第 安 大 学 的 校 号 就 可 以 集 中 跟 踪 了 反 复 行 gmodel.py 来 看 数 据, 通 添 加 映 射 数 据 更 加 干 程 序 一 旦 完 成, 你 会 得 到 一 个 子 件 的 索 引 版 本, 即 index.sqlite 个 数 据 文 件 用 于 数 据 分 析 非 常 快 首 先, 做 个 的 数 据 分 析 : 送 件 最 多? 和 个 送 件 最 多? 使 用 gbasic.py : How many to dump? 5 Loaded messages= 51330 subjects= 25033 senders= 1584 Top 5 Email list participants steve.swinsburg@gmail.com 2657 azeckoski@unicon.net 1742 ieb@tfd.co.uk 1591 csev@umich.edu 1304 david.horwitz@uct.ac.za 1184 Top 5 Email list organizations gmail.com 7339 umich.edu 6243 uct.ac.za 2451 indiana.edu 2258 unicon.net 2055 注 意, 与 gmane.py 和 gmodel.py 相 比,gbasic.py 理 数 据 非 常 快 然 它 都 在 相 同 的 数 据 上 工 作, 但 gbasic.py 使 用 index.sqlite 中 和 范 化 的 数 据 如 果 有 大 量 数 据 需 要 管 理, 本 示 例 用 程 序 采 用 的 多 步 理 可 能 多 用 了 一 些 开, 但 在 数 据 探 索 与 可 化 省 了 大 量 gword.py 了 主 行 的 可 化 : Range of counts: 33229 129 Output written to gword.js gword.py 行 后 生 成 gword.js 文 件, 通 gword.htm 行 可 化, 生 成 一 个 似 本 开 的 云 第 二 个 可 化 用 gline.py 生 成 它 算 了 一 段 内 某 的 子 件 参 与 情 况 Loaded messages= 51330 subjects= 25033 senders= 1584 Top 10 Oranizations ['gmail.com', 'umich.edu', 'uct.ac.za', 'indiana.edu', 'unicon.net', 'tfd.co.uk', 'berkeley.edu', 'longsight.com', 'stanford.edu', 'ox.ac.uk'] Output written to gline.js gline.py 行 后 生 成 gline.js 文 件, 通 gline.htm 行 可 化 数 据 可 化 146

以 上 是 一 个 相 复 的 高 用 程 序, 具 一 些 数 据 索 清 洗 与 可 化 功 能 数 据 可 化 147

第 16 章 常 任 自 化 理 我 已 学 了 从 文 件 网 Web Services 和 数 据 中 取 数 据 Python 可 以 遍 算 机 的 所 有 目 和 文 件, 并 取 些 文 件 本 章 中 写 的 程 序 会 描 算 机, 每 个 文 件 行 某 些 操 作 文 件 被 到 目 中, 也 称 文 件 的 Python 脚 本 既 能 快 速 解 决 任, 也 能 目 或 整 个 算 机 上 成 百 上 千 的 文 件 使 用 os.walk 和 for 循 遍 目 中 的 所 有 目 与 文 件 与 open 方 法 循 取 文 件 内 容 套 接 字 通 写 循 取 网 接 中 的 内 容 以 及 urllib 打 开 网 取 所 有 内 容 等 的 原 理 似 16.1 文 件 名 与 路 径 每 个 行 中 的 程 序 有 一 个 当 前 目, 作 大 多 数 操 作 的 默 目 例 如, 当 打 开 一 个 文 件 行 取,Python 会 在 当 前 目 下 找 个 文 件 os( 代 表 operating system, 操 作 系 ) 模 提 供 文 件 与 目 的 操 作 功 能 os.getcwd 返 回 当 前 目 的 名 称 : >>> import os >>> cwd = os.getcwd() >>> print cwd /Users/csev cwd 代 表 当 前 工 作 目 个 示 例 程 序 的 行 果 是 /Users/csev, 是 用 csev 的 当 前 目 似 cwd 的 字 符 串 表 示 的 是 路 径 相 路 径 从 当 前 目 开 始, 路 径 从 文 件 系 的 目 开 始 我 看 到 的 路 径 都 是 文 件 名, 因 此 它 是 相 于 当 前 目 的 找 到 一 个 文 件 的 路 径, 使 用 os.path.abspath: >>> os.path.abspath('memo.txt') '/Users/csev/memo.txt' os.path.exists 文 件 或 目 是 否 存 在 : >>> os.path.exists('memo.txt') True 如 果 存 在,os.path.isdir 它 是 否 是 一 个 目 : >>> os.path.isdir('memo.txt') False >>> os.path.isdir('music') True 同 地,os.path.isfile 它 是 否 是 一 个 文 件 os.listdir 根 据 指 定 目, 返 回 其 下 的 文 件 与 子 目 的 列 表 >>> os.listdir(cwd) 常 任 自 化 理 148

['music', 'photos', 'memo.txt'] 16.2 示 例 : 清 理 照 片 目 以 前 我 写 一 个 似 Flickr 的 件, 可 以 从 手 机 上 接 收 照 片, 并 把 它 存 在 服 器 上 我 写 个 件 Flickr 未 出, 当 Flickr 出 后, 我 仍 然 在 使 用 个 程 序, 用 来 保 留 原 始 照 片 我 会 在 彩 信 和 子 件 行 送 一 条 的 文 本 描 述 我 将 些 消 息 存 在 一 个 文 本 文 件 中, 放 置 在 照 片 文 件 所 在 的 目 下 根 据 照 片 拍 的 月 年 日 和 来 目 以 下 是 照 片 及 其 描 述 的 命 名 示 例 :./2006/03/24-03-06_2018002.jpg./2006/03/24-03-06_2018002.txt 七 年 之 后, 我 有 了 多 照 片 和 些 年 我 更 手 机, 从 消 息 中 抽 取 的 代 有 会 失 效, 服 器 上 出 了 一 些 无 用 的 数 据 我 想 要 遍 些 文 件, 找 出 些 文 本 文 件 是 真 正 的, 些 是 信 息, 然 后 除 些 信 息 首 先, 点 出 子 文 件 下 有 多 少 文 本 文 件, 行 以 下 程 序 : import os count = 0 for (dirname, dirs, files) in os.walk('.'): for filename in files: if filename.endswith('.txt') : count = count + 1 print 'Files:', count python txtcount.py Files: 1917 段 代 的 关 是 Python 的 os.walk 当 用 os.walk, 指 定 一 个 起 始 目, 它 会 式 遍 所 有 的 子 目. 表 示 当 前 目, 从 此 往 下 找 当 它 每 遇 到 一 个 目, 我 将 得 到 for 循 内 元 的 三 个 第 一 个 是 当 前 目 名, 第 二 个 是 当 前 目 的 子 目 列 表, 第 三 个 是 当 前 目 的 文 件 列 表 没 必 要 依 次 看 每 个 子 目 事 上, 通 os.walk 来 每 个 文 件 如 果 想 要 看 每 个 文 件, 写 一 个 的 for 循 来 看 当 前 目 下 的 每 个 文 件 如 果 文 件 以.txt 尾, 我 就 看 个 文 件, 并 整 个 目 中 以.txt 后 的 文 件 数 目 一 旦 知 道 了 有 多 少 文 件 以.txt 尾, 接 下 来 要 自 判 断 文 件 的 好 坏 因 此, 我 一 个 的 程 序, 打 印 出 文 件 及 其 大 小 : import os from os.path import join for (dirname, dirs, files) in os.walk('.'): for filename in files: if filename.endswith('.txt') : thefile = os.path.join(dirname,filename) print os.path.getsize(thefile), thefile 在, 不 要 文 件 数, 我 使 用 os.path.join 建 一 个 文 件 名, 将 目 中 的 文 件 名 与 目 名 接 在 一 起 里 使 用 os.path.join, 而 不 是 用 字 符 串 接 做 的 原 因 在 于 :Windows 上 使 用 反 斜 杠 (\) 来 造 文 件 路 径,Linux 和 Mac 上 使 用 正 斜 杠 (/) 来 造 文 件 路 径 os.path.join 知 道 如 何 理 一 差 异, 能 当 前 行 的 操 作 系, 据 此 适 合 的 接 因 此, 相 同 的 Python 代 在 Windows 和 Unix 系 上 都 能 行 一 旦 得 到 了 有 目 路 径 的 完 整 文 件 名, 使 用 os.path.getsize 取 文 件 大 小, 并 打 印 出, 程 序 行 果 如 下 : 常 任 自 化 理 149

python txtsize.py... 18./2006/03/24-03-06_2303002.txt 22./2006/03/25-03-06_1340001.txt 22./2006/03/25-03-06_2034001.txt... 2565./2005/09/28-09-05_1043004.txt 2565./2005/09/28-09-05_1141002.txt... 2578./2006/03/27-03-06_1618001.txt 2578./2006/03/28-03-06_2109001.txt 2578./2006/03/29-03-06_1355001.txt... 一 下 程 序 出, 我 注 意 到 有 一 些 文 件 很 短, 有 些 文 件 非 常 大, 有 一 些 相 同 大 小 的 文 件 (2578 和 2565) 当 打 开 一 些 大 文 件, 我 它 除 了 一 些 通 用 的 HTML 之 外, 其 他 什 么 都 没 有 那 些 HTML 从 我 的 T-Moblie 手 机 送 的 消 息 <html>... <head> <title>t-mobile</title> 跳 个 文 件, 它 看 起 来 没 有 包 含 有 用 的 信 息, 随 后 我 可 能 做 除 理 在 除 些 文 件 之 前, 我 写 一 个 程 序, 找 多 余 一 行 的 文 件, 并 示 文 件 的 内 容 不 要 被 2578 或 2565 字 符 度 的 文 件 所 干, 因 我 已 知 道 些 文 件 没 有 包 含 有 用 信 息 程 序 代 如 下 : import os from os.path import join for (dirname, dirs, files) in os.walk('.'): for filename in files: if filename.endswith('.txt') : thefile = os.path.join(dirname,filename) size = os.path.getsize(thefile) if size == 2578 or size == 2565: continue fhand = open(thefile,'r') lines = list() for line in fhand: lines.append(line) fhand.close() if len(lines) > 1: print len(lines), thefile print lines[:4] 我 使 用 continue 跳 个 大 小 不 正 确 的 文 件, 然 后 打 开 其 他 文 件, 将 取 到 文 件 的 内 容 放 到 一 个 Python 列 表 中 如 果 文 件 多 余 一 行, 打 印 出 文 件 的 行 数 和 前 三 行 内 容 一 来, 程 序 掉 个 大 小 不 正 确 的 文 件 假 所 有 行 的 文 件 是 正 确 的, 那 么 我 得 到 一 些 符 合 要 求 的 数 据 : python txtcheck.py 3./2004/03/22-03-04_2015.txt ['Little horse rider\r\n', '\r\n', '\r'] 2./2004/11/30-11-04_1834001.txt ['Testing 123.\n', '\n'] 3./2007/09/15-09-07_074202_03.txt ['\r\n', '\r\n', 'Sent from my iphone\r\n'] 3./2007/09/19-09-07_124857_01.txt ['\r\n', '\r\n', 'Sent from my iphone\r\n'] 3./2007/09/20-09-07_115617_01.txt 常 任 自 化 理 150

但 是, 文 件 中 是 存 在 一 个 或 多 个 令 人 疼 的 模 式 : 有 一 些 三 行 文 件, 包 含 个 空 行, 之 后 跟 一 行 文 字 自 我 的 iphone, 的 数 据 仍 然 存 在 因 此, 个 情 况 修 改 程 序 如 下 : lines = list() for line in fhand: lines.append(line) if len(lines) == 3 and lines[2].startswith('sent from my iphone'): continue if len(lines) > 1: print len(lines), thefile print lines[:4] 如 果 是 三 行 文 件, 程 序 其 行 ; 如 果 第 三 行 以 特 定 内 容 开 始, 跳 它 在 行 个 程 序, 我 看 到 有 4 个 多 行 文 件, 但 些 文 件 看 起 来 是 合 理 的 : python txtcheck2.py 3./2004/03/22-03-04_2015.txt ['Little horse rider\r\n', '\r\n', '\r'] 2./2004/11/30-11-04_1834001.txt ['Testing 123.\n', '\n'] 2./2006/03/17-03-06_1806001.txt ['On the road again...\r\n', '\r\n'] 2./2006/03/24-03-06_1740001.txt ['On the road again...\r\n', '\r\n'] 程 序 的 整 体 模 式, 通 接 受 或 拒 文 件, 果 行 清 理 一 旦 找 到 坏 模 式, 使 用 continue 跳 不 符 合 要 求 的 文 件 代 行 修 正, 找 到 更 多 不 符 合 要 求 的 文 件 模 式 在, 我 准 除 些 文 件 里 反 下, 不 打 印 出 剩 下 的 好 文 件, 而 是 打 印 出 那 些 不 符 合 要 求 准 除 的 文 件 import os from os.path import join for (dirname, dirs, files) in os.walk('.'): for filename in files: if filename.endswith('.txt') : thefile = os.path.join(dirname,filename) size = os.path.getsize(thefile) if size == 2578 or size == 2565: print 'T-Mobile:',thefile continue fhand = open(thefile,'r') lines = list() for line in fhand: lines.append(line) fhand.close() if len(lines) == 3 and lines[2].startswith('sent from my iphone'): print 'iphone:', thefile 我 得 到 了 一 个 待 除 的 候 文 件 列 表, 明 白 了 什 么 些 文 件 会 被 除 程 序 行 果 如 下 : python txtcheck3.py... T-Mobile:./2006/05/31-05-06_1540001.txt T-Mobile:./2006/05/31-05-06_1648001.txt iphone:./2007/09/15-09-07_074202_03.txt iphone:./2007/09/15-09-07_144641_01.txt iphone:./2007/09/19-09-07_124857_01.txt... 常 任 自 化 理 151

我 可 以 些 文 件, 确 保 没 有 在 不 意 引 入 致 程 序 束, 或 是 由 于 致 一 些 文 件 被 抓 当 我 待 除 的 列 表 感 到 意, 程 序 做 出 如 下 修 改 : if size == 2578 or size == 2565: print 'T-Mobile:',thefile os.remove(thefile) continue... if len(lines) == 3 and lines[2].startswith('sent from my iphone'): print 'iphone:', thefile os.remove(thefile) continue 在 个 版 本 的 程 序 中, 我 不 打 印 出 文 件, 使 用 os.remove 移 除 不 符 合 要 求 的 文 件 python txtdelete.py T-Mobile:./2005/01/02-01-05_1356001.txt T-Mobile:./2005/01/02-01-05_1858001.txt... 出 于 目 的, 再 行 一 遍 程 序, 次 不 会 出 任 何 果, 是 因 不 符 合 要 求 的 文 件 已 被 移 除 了 如 果 再 次 行 txtcount.py,899 个 不 符 合 要 求 的 文 件 会 被 移 除 python txtcount.py Files: 1018 在 本 中, 我 遵 循 一 定 理 步 首 先, 使 用 Python 遍 目 和 文 件 来 找 模 式 ; 然 后, 我 在 Python 的 帮 助 下, 确 定 目 中 些 内 容 需 要 行 清 理, 一 旦 找 到 些 文 件 符 合 要 求, 出 些 文 件 没 有 用 ; 最 后, 使 用 Python 行 清 理, 除 那 些 没 有 用 的 文 件 需 要 解 决 的 可 能 非 常, 可 能 需 要 看 文 件 名, 或 逐 个 入 文 件, 找 文 件 中 存 在 的 模 式 有, 你 需 要 取 所 有 文 件, 修 改 其 中 一 些 文 件 当 掌 握 了 os.walk 与 其 他 os 用 工 具 之 后, 些 操 作 会 得 非 常 16.3 命 令 行 参 数 前 面 章 中 的 很 多 程 序 都 使 用 raw_input 文 件 名 的 入, 从 文 件 取 数 据 整 个 数 据 理 程 如 下 : name = raw_input('enter file:') handle = open(name, 'r') text = handle.read()... 个 程 序 做 一 些 化, 在 Python, 通 命 令 行 取 得 文 件 名 行 Python 程 序, 提 示 如 下 : python words.py Enter file: mbox-short.txt... 我 可 以 在 Python 文 件 后 面 附 加 其 他 字 符 串, 在 Python 程 序 中 些 命 令 行 参 数 下 面 的 程 序 演 示 了 从 命 令 行 取 参 数 : 常 任 自 化 理 152

import sys print 'Count:', len(sys.argv) print 'Type:', type(sys.argv) for arg in sys.argv: print 'Argument:', arg sys.argv 的 内 容 是 一 个 字 符 串 列 表, 其 中 第 一 个 字 符 串 是 Python 程 序 的 名 称,Python 文 件 之 后 其 他 字 符 串 是 命 令 行 参 数 下 面 的 程 序 从 命 令 行 取 了 几 个 参 数 : python argtest.py hello there Count: 3 Type: <type 'list'> Argument: argtest.py Argument: hello Argument: there 三 个 参 数 作 三 元 列 表 到 程 序 中 列 表 的 第 一 个 元 素 是 文 件 名 (argtest.py), 文 件 名 之 后 的 其 他 个 是 命 令 行 参 数 我 重 写 个 程 序 来 取 文 件, 从 命 令 行 参 数 得 文 件 名, 程 序 代 如 下 : import sys name = sys.argv[1] handle = open(name, 'r') text = handle.read() print name, 'is', len(text), 'bytes' 我 把 第 二 个 命 令 行 参 数 作 文 件 名, 在 [0] 跳 之 前 的 程 序 名 打 开 文 件 并 取 文 件 内 容 的 代 如 下 所 示 : python argfile.py mbox-short.txt mbox-short.txt is 94626 bytes 使 用 命 令 行 参 数 作 入, 使 得 Python 程 序 更 易 于 重 用 特 是 有 一 个 或 个 字 符 串 入 的 情 况 有 用 16.4 管 道 大 多 数 操 作 系 提 供 命 令 行 界 面, 也 被 称 Shell Shell 通 常 提 供 文 件 系 航 与 用 的 命 令 例 如, 在 Unix 中,cd 命 令 更 改 目,ls 示 目 的 内 容, 入 如 Firefox 来 网 器 从 Shell 可 以 任 何 程 序, 也 可 以 通 Python 的 管 道 (pipe) 来 程 序 管 道 是 用 来 表 示 正 在 行 的 程 的 一 个 象 例 如,Unix 的 命 令 1 ls l 通 常 以 格 式 示 当 前 目 的 内 容 你 可 以 用 os.open 来 ls 命 令 : >>> cmd = 'ls -l' >>> fp = os.popen(cmd) 参 数 是 包 含 Shell 命 令 的 字 符 串 返 回 是 一 个 文 件 指, 个 程 就 像 是 打 开 一 个 文 件 通 ls 程,readline 每 次 取 一 行, 或 使 用 read 方 法 一 次 性 得 到 全 部 内 容 : >>> res = fp.read() 常 任 自 化 理 153

完 成 之 后, 像 关 文 件 一 关 管 道 : >>> stat = fp.close() >>> print stat None 返 回 是 ls 程 的 最 状 None 表 示 正 常 束, 没 有 出 16.5 路 径 : 从 目 开 始, 文 件 或 目 所 在 的 位 置 无 是 否 在 当 前 工 作 目, 都 可 以 到 文 件 或 目 校 : 参 哈 希 算 法 (hashing) 校 个 来 自 于 数 据 的 需 求, 当 数 据 在 网 上 送 或 写 入 到 份 介 后 再 行 取 的 程 中, 数 据 是 否 存 在 被 改 的 可 能 当 数 据 写 入 或 送, 送 系 会 算 出 校, 一 并 送 出 去 当 数 据 入 和 收 到, 接 收 系 会 根 据 接 收 到 的 数 据, 重 新 算 校, 与 送 来 的 校 行 比 如 果 校 不 匹 配, 那 么 就 会 数 据 在 程 中 被 改 了 命 令 行 参 数 :Python 文 件 名 之 后 命 令 行 中 的 参 数 当 前 工 作 目 : 当 前 你 所 在 的 目 在 大 多 数 系 的 命 令 行 界 面, 使 用 cd 命 令 更 改 工 作 目 在 Python 中, 使 用 文 件 名 打 开 文 件, 并 没 有 指 定 路 径 信 息, 文 件 必 在 当 前 行 程 序 的 工 作 目 下 哈 希 算 法 : 取 潜 在 的 大 量 数 据, 数 据 生 成 一 个 唯 一 的 校 最 佳 的 哈 希 函 数 只 生 很 少 的 冲 突 里 的 冲 突 是 指 哈 希 函 数 个 不 同 的 数 据 流, 生 相 同 的 哈 希 MD5 SHA1 和 SHA256 是 常 用 的 哈 希 算 法 管 道 : 与 正 在 行 的 程 序 行 接 的 通 道 通 管 道, 你 可 以 写 程 序 来 送 数 据 其 他 程 序, 或 从 其 他 程 序 接 收 数 据 管 道 与 套 接 字 似, 但 是 管 道 只 能 用 于 同 一 台 算 机 上 程 序 之 的 接, 也 就 是 不 能 通 网 行 接 相 路 径 : 相 于 当 前 的 工 作 目, 文 件 或 目 所 在 的 位 置 shell: 操 作 系 的 命 令 行 界 面 在 一 些 操 作 系 中 称 端 程 序 在 命 令 行 界 面 中, 入 一 条 命 令 和 参 数, 然 后 按 下 回 来 行 条 命 令 遍 : 整 个 目 子 目 以 及 子 目 的 子 目, 直 到 到 所 有 的 目 称 之 遍 目 16.6 16.1: 大 量 MP3 文 件 集 合 中 可 能 存 在 相 同 歌 曲 的 多 个 副 本, 存 于 不 同 的 目 或 者 以 不 同 的 文 件 命 名 个 的 目 是 找 到 重 复 的 MP3 文 件 1. 写 一 个 程 序, 遍 一 个 文 件 及 其 子 文 件 中 的 所 有 以.mp3 后 尾 的 文 件, 并 列 出 相 同 大 小 的 一 文 件 提 示 : 使 用 字 典, 字 典 的 是 从 os.path.getsize 得 到 的 文 件 大 小, 字 典 的 是 文 件 名 与 路 径 名 的 合 每 遇 到 一 个 文 件, 其 是 否 与 已 知 文 件 的 大 小 相 同 如 果 大 小 相 同, 得 到 一 个 重 复 大 小 的 文 件, 打 印 文 件 大 小 与 个 文 件 的 名 称 ( 一 个 来 自 哈 希, 一 个 是 你 正 在 看 的 文 件 ) 2. 修 改 之 前 的 程 序, 用 哈 希 或 校 算 法 看 重 复 内 容 的 文 件 例 如,MD5(Message-Digest algorithm 5, 消 息 摘 要 算 法 第 五 版 ) 接 受 任 意 度 的 消 息, 返 回 一 个 128 位 的 校 不 同 内 容 的 个 文 件 返 回 相 同 校 的 可 能 性 非 常 小 MD5 的 具 体 内 容 http://wikipedia.org/wiki/md5 以 下 代 片 段 打 开 一 个 文 件, 入 内 容, 算 校 import hashlib... fhand = open(thefile,'r') data = fhand.read() fhand.close() checksum = hashlib.md5(data).hexdigest() 常 任 自 化 理 154

新 建 一 个 字 典, 包 含 校 作, 文 件 名 作 当 算 了 校, 它 就 作 字 典 的 存 在, 有 个 文 件 内 容 重 复, 因 此 打 印 出 字 典 中 的 文 件 和 才 的 文 件 在 像 文 件 的 文 件 下 行 程 序, 果 如 下 所 示 :./2004/11/15-11-04_0923001.jpg./2004/11/15-11-04_1016001.jpg./2005/06/28-06-05_1500001.jpg./2005/06/28-06-05_1502001.jpg./2006/08/11-08-06_205948_01.jpg./2006/08/12-08-06_155318_02.jpg 很 然, 我 重 复 提 交 了 相 同 的 照 片, 没 有 及 除 之 前 的 拷 1. 当 使 用 管 道 与 操 作 系 命 令 ( 如 ls), 有 一 点 很 重 要, 了 解 正 在 使 用 的 操 作 系 型, 使 用 管 道 打 开 操 作 系 支 持 的 命 令 常 任 自 化 理 155

附 A Windows 平 台 上 的 Python 程 本 附 介 在 Windows 上 行 Python 的 一 系 列 步 你 可 以 采 用 多 种 方 法 做 到 一 点, 但 是 一 种 事 情 保 持 的 方 法 首 先, 你 需 要 安 装 一 个 程 序 用 的 器 不 要 使 用 事 本 或 微 的 Word 字 理 件 来 Python 程 序 程 序 必 是 平 面 的 文 本 文 件, 因 此 你 需 要 的 是 一 个 擅 文 本 文 件 的 器 我 在 Windows 平 台 上 推 荐 NotePad++, 从 以 下 网 址 下 与 安 装 : http://sourceforge.net/projects/notepad-plus/files/ 从 www.python.org 网 站 下 Python 2 的 最 新 版 本 http://www.python.org/download/releases/2.7.5/ 安 装 好 Python 之 后, 算 机 上 会 出 似 的 新 文 件 C:\Python27 新 建 一 个 Python 程 序, 从 开 始 菜 行 NotePad++, 采 用.py 后 保 存 文 件 个 中, 在 桌 面 建 一 个 py4inf 文 件 文 件 名 越 短 越 好, 不 要 在 文 件 和 文 件 名 中 留 空 格 写 第 一 个 Python 程 序 如 下 : print 'Hello Chuck' 里 你 能 做 的 就 是 修 改 成 你 自 己 的 名 字 将 程 序 文 件 保 存 在 Desktop\py4inf\prog1.py 在 命 令 行 行 程 序,Windows 不 同 版 本 的 操 作 有 些 差 Windows Vista 与 Windows-7: 按 下 开 始 按, 在 命 令 搜 索 窗 口 入 command 一, 然 后 按 回 Windows-XP: 按 下 开 始 按, 然 后 点 行, 在 框 入 cmd, 然 后 点 OK 此 出 一 个 文 本 窗 口, 并 提 示 当 前 所 在 的 文 件 Windows Vista 与 Windows-7 的 文 件 位 置 是 :C:\Users\csev Windows XP 的 文 件 位 置 是 :C:\Documents and Settings\csev 就 是 你 的 主 目 在 我 需 要 入 才 保 存 Python 程 序 的 文 件, 使 用 以 下 命 令 : C:\Users\csev\> cd Desktop C:\Users\csev\Desktop> cd py4inf 然 后 入 C:\Users\csev\Desktop\py4inf> dir 列 出 当 前 文 件 下 的 所 有 文 件 当 入 dir 命 令 后, 你 看 到 prog1.py 文 件 了 行 个 程 序, 只 需 在 命 令 行 入 文 件 名, 然 后 按 回 C:\Users\csev\Desktop\py4inf> prog1.py Hello Chuck C:\Users\csev\Desktop\py4inf> 附 A 156

你 可 以 在 NotePad++ 里 写 文 件, 保 存 它 然 后, 切 到 命 令 行 窗 口, 在 命 令 行 提 示 符, 入 文 件 名 再 次 行 程 序 如 果 你 被 命 令 行 窗 口 搞 混 了, 没 关 系, 关 它 再 打 开 一 个 即 可 提 示 : 在 命 令 行 使 用 向 上 箭 可 以 回 和 行 之 前 入 的 命 令 外, 建 在 NotePad++ 的 偏 好 置 中 将 Tab 字 符 置 4 个 空 格 将 省 大 量 由 于 致 的 花 Python 程 序 与 行 的 更 多 信 息, 参 http://www.py4inf.com 附 A 157

附 B Mac 平 台 上 的 Python 程 本 附 介 在 Mac 上 行 Python 的 系 列 步 由 于 Mac 操 作 系 已 包 含 了 Python, 所 以 只 需 学 如 何 Python 文 件 和 在 端 窗 口 行 Python 程 序 在 Python 程 序 与 行 的 多 方 法 中, 是 我 找 到 的 一 种 非 常 的 方 法 首 先, 需 要 安 装 一 个 程 序 用 的 文 本 器 不 要 使 用 TextEdit 或 微 的 Word 字 理 件 来 程 序 程 序 必 是 平 的 文 本 文 件, 因 此 你 需 要 的 是 一 个 善 于 文 本 文 件 的 器 我 在 Mac 平 台 上 推 荐 TextWrangler, 从 以 下 网 址 下 与 安 装 : http://www.barebones.com/products/textwrangler/ 新 建 一 个 Python 程 序, 从 用 文 件 中 行 TextWrangler 写 第 一 个 Python 程 序 : print 'Hello Chuck' 里 你 能 做 的 就 是 修 改 成 你 自 己 的 名 字 将 程 序 文 件 保 存 在 桌 面, 命 名 py4inf 文 件 名 越 短 越 好, 不 要 在 文 件 和 文 件 名 中 留 空 格 在 端 窗 口 行 程 序 最 的 方 法 是 点 屏 幕 后 上 角 的 Spotlight ( 放 大 ), 入 terminal ( 也 可 入 中 文 端 ) 端 窗 口 就 是 你 的 主 目 在 端 窗 口 入 pwd 命 令 看 当 前 目 67-194-80-15:~ csev$ pwd /Users/csev 67-194-80-15:~ csev$ 必 在 包 含 Python 程 序 的 文 件 下 行 程 序 我 使 用 cd 命 令 移 到 一 个 新 的 文 件, 然 后 用 ls 命 令 列 出 文 件 下 的 文 件 67-194-80-15:~ csev$ cd Desktop 67-194-80-15:Desktop csev$ cd py4inf 67-194-80-15:py4inf csev$ ls prog1.py 67-194-80-15:py4inf csev$ 在 命 令 提 示 符, 只 需 入 python 命 令 来 行 程 序, 后 面 跟 程 序 文 件 名, 然 后 按 回 67-194-80-15:py4inf csev$ python prog1.py Hello Chuck 67-194-80-15:py4inf csev$ 在 TextWrangler Python 程 序 文 件, 保 存 它, 然 后 切 到 命 令 行 窗 口, 在 命 令 行 提 示 符, 入 文 件 名 再 次 行 程 序 提 示 : 在 命 令 行 使 用 向 上 箭 可 以 回 和 行 之 前 入 的 命 令 外, 建 在 TextWrangler 的 偏 好 置 中 将 Tab 字 符 置 4 个 空 格 将 省 大 量 由 于 致 的 花 附 B 158

Python 程 序 与 行 的 更 多 信 息, 参 http://www.py4inf.com 附 B 159

附 C 献 信 息 管 理 Python 教 程 献 者 名 Bruce Shields 了 早 期 稿,Sarah Hegge, Steven Cherry, Sarah Kathleen Barbarow, Andrea Parker, Radaphat Chongthammakun, Megan Hixon, Kirby Urner, Sarah Kathleen Barbrow, Katie Kujala, Noah Botimer, Emily Alinder, Mark Thompson-Kular, James Perry, Eric Hofer, Eytan Adar, Peter Robinson, Deborah J. Nelson, Jonathan C. Anthony, Eden Rassette, Jeannette Schroeder, Justin Feezell, Chuanqi Li, Gerald Gordinier, Gavin Thomas Strassel, Ryan Clement, Alissa Talley, Caitlin Holman, Yong-Mi Kim, Karen Stover, Cherie Edmonds, Maria Seiferle, Romer Kristi D. Aranas (RK), Grant Boyer, Hedemarrie Dussan, 思 考 Python 序 思 考 Python 怪 史 (Allen B. Downey) 1999 年 1 月 我 准 授 一 Java 程 入 程 我 已 三 遍, 但 令 我 很 沮 程 的 失 比 例 太 高, 即 便 是 成 功 的 学 生 也 感 不 好, 整 体 的 成 就 感 非 常 低 我 之 一 是 教 材 它 都 是 大 部, 介 了 太 多 不 必 要 的 Java, 并 没 有 出 足 多 的 如 何 程 的 高 水 平 的 引 学 生 都 体 到 陷 效 : 他 一 开 始 得 容 易, 循 序, 然 后 到 第 五 章 左 右 就 脱 了 学 生 得 到 很 多 新 内 容 度 太 快 了, 我 得 用 学 期 剩 下 的 收 拾 残 局 在 第 一 次 之 前 的 周, 我 决 定 写 一 本 我 自 己 的 我 的 目 是 : 保 持 短 学 生 10 比 50 的 效 果 要 好 慎 使 用 我 尽 量 少 用 行, 在 第 一 次 使 用 每 个 行 定 循 序 避 免 陷, 我 将 最 困 的 主 分 解 成 一 系 列 小 的 步 注 于 程, 而 不 是 程 言 我 只 解 Java 有 用 的 最 小 子 集, 其 他 不 涉 及 我 需 要 一 个 名, 一 起, 想 出 了 像 算 机 科 学 家 一 思 考 么 一 个 名 字 第 一 个 版 本 非 常 粗 糙, 但 是 起 作 用 了 学 生 真 得 去 了, 他 能 充 分 理 解 我 在 堂 上 花 授 的 复 主, 有 趣 的 主 和 最 重 要 的 部 分 留 他 下 去 我 使 用 GNU 自 由 文 档 可 布 本, 允 用 复 制 修 改 和 分 本 接 下 来 生 的 事 情 是 最 酷 的 部 分 一 位 弗 吉 尼 州 的 高 中 老 Jeff Elkner 改 了 我 的, 把 它 改 成 Python 言 他 我 一 份 稿, 我 通 自 己 的 来 学 Python, 是 多 么 不 常 的 体 啊 Jeff 和 我 修 了 本, 加 入 了 Chris Meyers 的 一 个 案 例 研 究 2001 年 我 是 以 GNU 自 由 文 档 布 了 像 算 机 科 学 家 一 思 考 : 学 Python 通 茶 出 版 社, 我 出 版 了 本, 开 始 在 Amazon.com 和 大 学 店 出 售 茶 出 版 社 出 版 的 其 他 籍 http://greenteapress.com 2003 年 我 开 始 在 奥 林 学 院 教, 第 一 次 授 Python 与 Java 的 比 是 人 的 学 生 扎 更 少, 学 到 更 多, 开 了 更 多 有 趣 的 目, 体 而 言 趣 更 多 在 去 5 年 里, 我 不 断 修 本, 和 改 一 些 示 例, 增 加 内 容, 特 是 2008 年 我 开 始 了 一 个 重 大 版 本 修, 与 此 同 大 学 出 版 社 一 位 系 我, 出 版 此 新 版 表 出 趣 多 好 的 机! 我 希 望 你 能 喜 本, 它 能 帮 助 你 学 程 与 思 考, 至 少 有 那 么 一 点 点 像 算 机 科 学 家 附 C 160

思 考 Python 致 (Allen B. Downey) 首 先 也 是 最 重 要 的, 我 要 感 Jeff Elkner, 他 将 我 的 Java 翻 成 Python 版 本, 促 使 个 目 得 以, 也 我 到 了 自 己 最 喜 的 言 我 也 要 感 Chris Meyers, 他 献 了 像 算 机 科 学 家 一 思 考 的 若 干 内 容 我 要 感 自 由 件 基 金 会 提 出 的 GNU 自 由 文 档 可, 我 与 Jeff 和 Chris 共 事 成 可 能 我 要 感 像 算 机 科 学 家 一 思 考 的 Lulu 网 任 我 要 感 所 有 参 与 到 本 早 期 版 本 写 的 学 生, 所 有 提 交 勘 与 建 的 献 者 名 字 示 在 附 中 我 要 感 我 的 妻 子 Lisa 本 的 付 出, 有 茶 出 版 社 和 其 他 所 有 提 供 帮 助 的 人 Allen B. Downey Needham MA Allen Downey 是 富 克 林. 奥 林 工 程 学 院 算 机 科 学 副 教 授 思 考 Python 献 者 名 在 去 几 年, 有 100 多 位 眼 光 敏 有 想 法 的 者 出 建 和 提 交 勘 他 个 目 的 献 与 情, 成 最 大 的 帮 助 每 个 人 的 献 参 思 考 Python 正 文 Lloyd Hugh Allen, Yvon Boulianne, Fred Bremmer, Jonah Cohen, Michael Conlon, Benoit Girard, Courtney Gleason and Katherine Smith, Lee Harr, James Kaylin, David Kershaw, Eddie Lam, Man-Yong Lee, David Mayo, Chris McAloon, Matthew J. Moelter, Simon Dicon Montford, John Ouzts, Kevin Parks, David Pool, Michael Schmitt, Robin Shaw, Paul Sleigh, Craig T. Snydal, Ian Thomas, Keith Verheyden, Peter Winstanley, Chris Wrobel, Moshe Zadka, Christoph Zwerschke, James Mayer, Hayden McAfee, Angel Arnal, Tauhidul Hoque and Lex Berezhny, Dr. Michele Alzetta, Andy Mitchell, Kalin Harvey, Christopher P. Smith, David Hutchins, Gregor Lingl, Julie Peters, Florin Oprina, D. J. Webre, Ken, Ivo Wever, Curtis Yanko, Ben Logan, Jason Armstrong, Louis Cordier, Brian Cain, Rob Black, Jean-Philippe Rey at Ecole Centrale Paris, Jason Mader at George Washington University made a number Jan Gundtofte-Bruun, Abel David and Alexis Dinno, Charles Thayer, Roger Sperberg, Sam Bull, Andrew Cheung, C. Corey Capel, Alessandra, Wim Champagne, Douglas Wright, Jared Spindor, Lin Peiheng, Ray Hagtvedt, Torsten Hübsch, Inga Petuhhov, Arne Babenhauserheide, Mark E. Casida, Scott Tyler, Gordon Shephard, Andrew Turner, Adam Hobart, Daryl Hammond and Sarah Zimmerman, George Sass, Brian Bingham, Leah Engelbert-Fenton, Joe Funke, Chao-chao Chen, Jeff Paine, Lubos Pintes, Gregg Lind and Abigail Heithoff, Max Hailperin, Chotipat Pornavalai, Stanislaw Antol, Eric Pashman, Miguel Azevedo, Jianhua Liu, Nick King, Martin Zuther, Adam Zimmerman, Ratnakar Tiwari, Anurag Goel, Kelli Kratzer, Mark Griffiths, Roydan Ongie, Patryk Wolowiec, Mark Chonofsky, Russell Coleman, Wei Huang, Karen Barber, Nam Nguyen, Stéphane Morin, and Paul Stoop. 附 C 161