# 6.1 懒惰即美德
![](https://box.kancloud.cn/f0ceb48cf33ce537d5013c2578a7fb09_333x94.png)
![](https://box.kancloud.cn/e49f5157aacc60504863b2e120b57c2b_444x80.png)
![](https://box.kancloud.cn/3af97e05c79a5317b52a2c2a47e7b788_442x37.png)
# 6.2 抽象和结构
程序应该是非常抽象的,就像“下载网页、计算频率、打印每个单词的频率”一样易懂,事实上,我们现在就能把这段描述翻译成Python程序:
~~~
page = download_page()
freqs = compute_frequencies(page)
for word.freq in freqs:
print word.freq
~~~
# 6.3 创建函数
![](https://box.kancloud.cn/f8f1aa8278579e75797bbefb4c16b770_571x299.png)
里面说 callable 在 Python 3.0 中不在可用,但3.4.3 里可用啊。
![](https://box.kancloud.cn/7c35b228b6e38c3ae4cd89f030e13bc3_596x224.png)
## 6.3.1 记录函数
如果想要给函数写文档,让后面使用该函数人能理解的话,可以加入注释(以#开头)。另外一个方式就是直接写上字符串。如果在函数的开头写下字符串,它就会作为函数的一部分进行存储,这称为文档字符串。
![](https://box.kancloud.cn/6aac0b6ebfd28af39f0c842df05140f4_401x186.png)
## 6.3.2 并非真正函数的函数
数学意义上的函数,总在计算其参数后返回点什么。Python 的有些函数却不返回任何东西。在其他语言中(比如Pascal),这类函数可能有其他名字(比如过程)。但是Python的函数就是函数,即便它从学术上讲并不是函数。没有return语句,或者有return语句但return后边没有跟任何值的函数不返回值。
![](https://box.kancloud.cn/3ad512b7b92a385fe6bf0d830b3aa897_278x142.png)
# 6.4 参数魔法
## 6.4.1 值从哪里来
## 6.4.2 我能改参数吗
![](https://box.kancloud.cn/353c3ad2db9214f9b8f1c1ecdbdd19c5_355x177.png)
参数存储在局部作用域(local scope)内。
![](https://box.kancloud.cn/111ced6cc2cecd2b743c81d5e06b0ae5_330x101.png)
字符串(以及数字和元组)是不可变的,即无法被修改(也就是说只能用新的值覆盖)。如果将可变的数据结构如列表用作参数,其会被改变。
![](https://box.kancloud.cn/8de20638d4e77a597e7c5929694bf1cd_334x98.png)
为了防止这种情况出现,我们可以复制一个副本。
![](https://box.kancloud.cn/a9bb2c071ee615e707c3a4d9682bc12a_340x193.png)
参数n包含一个副本,而原始的列表是安全的。
1.为什么我想要修改参数
![](https://box.kancloud.cn/81476427b12d47947620b939b06466c7_497x374.png)
上面这些烦琐的过程怎样用函数来简化:
![](https://box.kancloud.cn/9f20427ccf3a09aab6d8fb037e76e252_368x349.png)
上面例子没看懂。
2.如果我的参数不可变呢
![](https://box.kancloud.cn/d43e1bd4c7f6ab4da8760cdd284eee0a_215x202.png)
## 6.4.3 关键字参数和默认值
![](https://box.kancloud.cn/57ac9f46ea85cadfcff88330945c3c86_405x411.png)
![](https://box.kancloud.cn/872e4d05e98798c7ddbf58c9db9aac7c_516x186.png)
## 6.4.4 收集参数
![](https://box.kancloud.cn/fd685536c0d4d63effe2c876512e847b_263x99.png)
参数前星号将所有值放置在同一个元组中。
![](https://box.kancloud.cn/dbb7d7522a5a433a08cc102dde010032_330x155.png)
星号的意思就是”收集其余的位置参数“。如果不提供任何供收集的元素,params 就是个空元组。
![](https://box.kancloud.cn/15dafc614b72804c097609179b58ebf5_593x147.png)
二个星返回的是字典。
![](https://box.kancloud.cn/f09af63e96a6bd26bc1311c4b6913a21_451x129.png)
![](https://box.kancloud.cn/de6028c91b9db3bc2836f7bad40ebcdd_405x378.png)
![](https://box.kancloud.cn/2fcf13118b7b8f5203ced4c320d7fdc7_776x58.png)
## 6.4.5 反转过程
![](https://box.kancloud.cn/dbbf28a0bcc74e0e1b7a61bece619d12_522x227.png)
![](https://box.kancloud.cn/5bcc963a1a3d9e98c645caca81a6cd27_495x241.png)
## 6.4.6 练习使用参数
![](https://box.kancloud.cn/4afee67fbf918ee7825b595b750d1c16_538x532.png)
![](https://box.kancloud.cn/c3b55b325a359ba5ae9817d5febf1f8b_523x398.png)
![](https://box.kancloud.cn/3219a79d7681a1a89ecd2994003e462c_516x237.png)
# 6.5 作用域
![](https://box.kancloud.cn/a4ea5062f69a03c2c2fb1749488a3f92_219x101.png)
![](https://box.kancloud.cn/6a5d22e685f51845ec3257758c32a133_194x93.png)
![](https://box.kancloud.cn/5c0db8481e6fc992fe62d8c38ba21428_245x84.png)
![](https://box.kancloud.cn/f56fffa18accbd574d6a315b5f484272_483x84.png)
警告:像这样引用全局变量是很多错误的引发原因,慎重使用。
![](https://box.kancloud.cn/6b5bc866e89f1f2200d4a005eb63b1e3_381x90.png)
![](https://box.kancloud.cn/399bccfe172f8041c9e725ade6765153_399x198.png)
嵌套作用域
![](https://box.kancloud.cn/b16a55da2c86dc8d4c14bc2639b95534_321x296.png)
类似multiplyByFactor函数存储子封闭作用域的行为叫闭包(closure).
# 6.6 递归
## 6.6.1 两个经典:阶乘和幂
![](https://box.kancloud.cn/1f0402ca22909ccfaebb005736ae9845_312x473.png)
## 6.6.2 另外一个经典:二元查找
# 6.7 小结
map(func, seq[, seq, ...]):对序列中的每个元素应用函数
filter(func, seq):返回其函数为真的元素的列表
reduce(func, seq[, initial]):等同于func(func(func(seq[0], seq[1]),seq[2])...)
sum(seq):返回seq中所有元素的和
apply(func[, args[, kwargs]]):调用函数,可以提供参数