566 lines
13 KiB
Plaintext
566 lines
13 KiB
Plaintext
|
{
|
|||
|
"cells": [
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"# 化名与匿名"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"## 化名"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"在 Python 中,我们可以给一个函数取个**化名**(alias)。\n",
|
|||
|
"\n",
|
|||
|
"以下的代码,我们先是定义了一个名为 `_is_leap` 的函数,而后为它另取了一个化名:"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 5,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"<function __main__._is_leap(year)>"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 5,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
},
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"True"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 5,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
},
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"4379191184"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 5,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
},
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"4379191184"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 5,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
},
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"function"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 5,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
},
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"function"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 5,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"from IPython.core.interactiveshell import InteractiveShell\n",
|
|||
|
"InteractiveShell.ast_node_interactivity = \"all\"\n",
|
|||
|
"\n",
|
|||
|
"def _is_leap(year):\n",
|
|||
|
" return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)\n",
|
|||
|
"\n",
|
|||
|
"year_leap_bool = _is_leap\n",
|
|||
|
"year_leap_bool #<function __main__._is_leap(year)>\n",
|
|||
|
"year_leap_bool(800) # _is_leap(800) -> True\n",
|
|||
|
"\n",
|
|||
|
"id(year_leap_bool) # id() 这个函数可以查询某对象的内存地址\n",
|
|||
|
"id(_is_leap) # year_leap_bool 和 _is_leap 其实保存在同一个地址中,也就是说,它们是同一个对象。\n",
|
|||
|
"\n",
|
|||
|
"type(year_leap_bool)\n",
|
|||
|
"type(_is_leap) # 它们都是 function"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"我们可以看到的是,`id(year_leap_bool)` 和 `id(_is_leap)` 的内存地址是一样的 —— 它们是同一个对象,它们都是函数。所以,当你写 `year_leap_bool = _is_leap` 的时候,相当于给 `_is_leap()` 这个函数取了个化名。"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"## lambda"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"写一个很短的函数可以用 `lambda` 关键字。\n",
|
|||
|
"\n",
|
|||
|
"下面是用 `def` 关键字写函数:"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 14,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"8"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 14,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"def add(x, y):\n",
|
|||
|
" return x + y\n",
|
|||
|
"add(3, 5)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"下面是用 `lambda` 关键字写函数:"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 17,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"8"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 17,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"add = lambda x, y: x + y\n",
|
|||
|
"add(3, 5)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"lambda 的语法结构如下:\n",
|
|||
|
"\n",
|
|||
|
"> `lambda_expr ::= \"lambda\" [parameter_list] \":\" expression`\n",
|
|||
|
"\n",
|
|||
|
"```python\n",
|
|||
|
"lambda x, y: x + y\n",
|
|||
|
"```\n",
|
|||
|
"\n",
|
|||
|
"先写上 `lambda` 这个关键字,其后分为两个部分,`:` 之前是参数,之后是表达式;这个表达式的值,就是这个函数的返回值。\n",
|
|||
|
"\n",
|
|||
|
"> **注意**:`lambda` 语句中,`:` 之后有且只能有一个表达式。\n",
|
|||
|
"\n",
|
|||
|
"而这个函数呢,没有名字,所以被称为 “匿名函数”。\n",
|
|||
|
"\n",
|
|||
|
"`add = lambda x, y: x + y`\n",
|
|||
|
"\n",
|
|||
|
"就相当于是给一个没有名字的函数取了个名字。"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"## lambda 的使用场景"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"那 lambda 这种匿名函数的用处在哪里呢?"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"### 作为某函数的返回值"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"第一个常见的用处是*作为另外一个函数的返回值*。\n",
|
|||
|
"\n",
|
|||
|
"让我们看看 [The Python Tutorial](https://docs.python.org/3/tutorial/controlflow.html#lambda-expressions) 中的一个例子。"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 22,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"42"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 22,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
},
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"43"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 22,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"def make_incrementor(n):\n",
|
|||
|
" return lambda x: x + n\n",
|
|||
|
"\n",
|
|||
|
"f = make_incrementor(42)\n",
|
|||
|
"f(0)\n",
|
|||
|
"\n",
|
|||
|
"f(1)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"这个例子乍看起来很令人迷惑。我们先看看 `f = make_incrementor(42)` 之后,`f` 究竟是什么东西:"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 23,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"<function __main__.make_incrementor.<locals>.<lambda>(x)>"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 23,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
},
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"4428443296"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 23,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
},
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"4428726888"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 23,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"def make_incrementor(n):\n",
|
|||
|
" return lambda x: x + n\n",
|
|||
|
"\n",
|
|||
|
"f = make_incrementor(42)\n",
|
|||
|
"f\n",
|
|||
|
"\n",
|
|||
|
"id(make_incrementor)\n",
|
|||
|
"id(f)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"首先,要注意,`f` 并不是 `make_incrementor()` 这个函数的化名,如果是给这个函数取个化名,写法应该是:\n",
|
|||
|
"\n",
|
|||
|
"```python\n",
|
|||
|
"f = make_incrementor\n",
|
|||
|
"```"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"那 `f` 是什么呢?它是 `<function __main__.make_incrementor.<locals>.<lambda>(x)>`:\n",
|
|||
|
"\n",
|
|||
|
"> * `f = make_incrementor(42)` 是将 `make_incrementor(42)` 的返回值保存到 `f` 这个变量之中;\n",
|
|||
|
"> * 而 `make_incrementor()` 这个函数接收到 `42` 这个参数之后,返回了一个函数:`lambda x: x + 42`;\n",
|
|||
|
"> * 于是,`f` 中保存的函数是 `lambda x: x + 42`;\n",
|
|||
|
"> * 所以,`f(0)` 是向这个匿名函数传递了 `0`,而后,它返回的是 `0 + 42`。"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"### 作为某函数的参数"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"可以拿一些可以接收函数为参数的内建函数做例子。比如,[`map()`](https://docs.python.org/3/library/functions.html#map)。\n",
|
|||
|
"\n",
|
|||
|
"> `map`(*function*, *iterable*, *...*)\n",
|
|||
|
"> \n",
|
|||
|
"> Return an iterator that applies *function* to every item of *iterable*, yielding the results. If additional *iterable* arguments are passed, *function* must take that many arguments and is applied to the items from all iterables in parallel. With multiple iterables, the iterator stops when the shortest iterable is exhausted. For cases where the function inputs are already arranged into argument tuples, see [`itertools.starmap()`](https://docs.python.org/3/library/itertools.html#itertools.starmap)."
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"`map()` 这个函数的第一个参数,就是用来接收函数的。随后的参数,是 `iterable` —— 就是可被迭代的对象,比如,各种容器,例如:列表、元组、字典什么的。"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 35,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"[2, 4, 6, 8, 10, 12]"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 35,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
},
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"[2, 4, 6, 8, 10, 12]"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 35,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"def double_it(n):\n",
|
|||
|
" return n * 2\n",
|
|||
|
"\n",
|
|||
|
"a_list = [1, 2, 3, 4, 5, 6]\n",
|
|||
|
"\n",
|
|||
|
"b_list = list(map(double_it, a_list))\n",
|
|||
|
"b_list\n",
|
|||
|
"\n",
|
|||
|
"c_list = list(map(lambda x: x * 2, a_list))\n",
|
|||
|
"c_list"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"显然用 `lambda` 更为简洁。另外,类似完成 `double_it(n)` 这种简单功能的函数,常常有 “用过即弃” 的必要。"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 60,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"[{'name': 'john', 'phone': 9876},\n",
|
|||
|
" {'name': 'mike', 'phone': 5603},\n",
|
|||
|
" {'name': 'stan', 'phone': 6898},\n",
|
|||
|
" {'name': 'eric', 'phone': 7898}]"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 60,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
},
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"['john', 'mike', 'stan', 'eric']"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 60,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
},
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"[9876, 5603, 6898, 7898]"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 60,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"phonebook = [\n",
|
|||
|
" {\n",
|
|||
|
" 'name': 'john',\n",
|
|||
|
" 'phone': 9876\n",
|
|||
|
" },\n",
|
|||
|
" {\n",
|
|||
|
" 'name': 'mike',\n",
|
|||
|
" 'phone': 5603\n",
|
|||
|
" },\n",
|
|||
|
" {\n",
|
|||
|
" 'name': 'stan',\n",
|
|||
|
" 'phone': 6898\n",
|
|||
|
" },\n",
|
|||
|
" {\n",
|
|||
|
" 'name': 'eric',\n",
|
|||
|
" 'phone': 7898\n",
|
|||
|
" }\n",
|
|||
|
"]\n",
|
|||
|
"\n",
|
|||
|
"phonebook\n",
|
|||
|
"list(map(lambda x: x['name'], phonebook))\n",
|
|||
|
"list(map(lambda x: x['phone'], phonebook))"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"可以给 map() 传递若干个可被迭代对象:"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 63,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"[2, 12, 30]"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 63,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"a_list = [1, 3, 5]\n",
|
|||
|
"b_list = [2, 4, 6]\n",
|
|||
|
"\n",
|
|||
|
"list(map(lambda x, y: x * y, a_list, b_list))"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"以上的例子都弄明白了,再去看 [The Python Tutorial](https://docs.python.org/3/tutorial/controlflow.html#lambda-expressions) 中的例子,就不会有任何疑惑了:"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 1,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"[(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 1,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]\n",
|
|||
|
"pairs.sort(key=lambda p: p[1])\n",
|
|||
|
"pairs"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"metadata": {
|
|||
|
"kernelspec": {
|
|||
|
"display_name": "Python 3",
|
|||
|
"language": "python",
|
|||
|
"name": "python3"
|
|||
|
},
|
|||
|
"language_info": {
|
|||
|
"codemirror_mode": {
|
|||
|
"name": "ipython",
|
|||
|
"version": 3
|
|||
|
},
|
|||
|
"file_extension": ".py",
|
|||
|
"mimetype": "text/x-python",
|
|||
|
"name": "python",
|
|||
|
"nbconvert_exporter": "python",
|
|||
|
"pygments_lexer": "ipython3",
|
|||
|
"version": "3.8.2"
|
|||
|
}
|
|||
|
},
|
|||
|
"nbformat": 4,
|
|||
|
"nbformat_minor": 2
|
|||
|
}
|