Skip to content

函数

8 / 44

函数实际上是可被调用的完整的程序它具备输入处理输出的功能又因为它经常在主程序里被调用所以它总是更像是个子程序

了解一个函数无非是要了解它的两个方面

  • 它的输入是怎么构成的都有哪些参数如何指定?);
  • 以及它的输出是什么返回值究竟是什么?)……

从这个角度看对人类来说就是个函数它吃的是挤出来的是…… 开玩笑了

在我们使用函数的过程中我们常常有意忽略它的内部如何完成从输入到输出之间的处理过程 —— 这就好像我们平日里用灯泡一样大多数情况下我们只要知道开关的使用方法就够了 —— 至于为什么按到这个方向上灯会亮为什么按到另外一个方向上灯会灭并不是我们作为用户必须关心的事情……

当然如果你是设计开关的人就不一样了你必须知道其中的运作原理但是最终你还是希望你的用户用最简单方便的操作界面而不是必须搞懂所有原理才能够使用你所设计的产品……

当我们用 Python 编程的时候更多的情况下我们只不过是在使用别人已经写好的函数或者用更专业一点的词藻叫做已完好封装的函数”。而我们所需要做的事情所谓的学习使用函数”),其实只不过是通过阅读产品说明书了解如何使用产品而已真的没多神秘……

注意

这一章的核心目的不是让你学会如何写函数而是通过一些例子让你大抵上学会如何阅读官方文档中关于函数的使用说明”。也请注意之前的那个词:“大抵上”,所以千万别怕自己最初的时候理解不全面

另外这一章中用来举例的函数全部来自于同一个官方文档页面Built-in Functions

https://docs.python.org/3/library/functions.html

示例 print()

基本的使用方法

print() 是初学者最常遇到的函数 —— 姑且不说是不是最常用到的

它最基本的作用就是把传递给它的值输出到屏幕上如果不给它任何参数那么它就输出一个空行

python
print('line 1st')
print('line 2nd')
print()
print('line 4th')
plaintext
line 1st
line 2nd

line 4th

你也可以向它传递多个参数参数之间用 , 分开它就会把那些值逐个输出到屏幕每个值之间默认用空格分开

python
print('Hello,', 'jack', 'mike', '...', 'and all you guys!')
plaintext
Hello, jack mike ... and all you guys!

当我们想把变量或者表达式的值插入字符串中的时候可以用 f-string:

python
name = 'Ann'
age = '22'
print(f'{name} is {age} years old.')
plaintext
Ann is 22 years old.

但这并不是 print() 这个函数的功能这实际上是 f-string 的功能f-string 中用花括号 {} 括起来的部分是表达式最终转换成字符串的时候那些表达式的值而不是变量或者表达式本身会被插入相应的位置……

python
name = 'Ann'
age = '22'
f'{name} is {age} years old.'
plaintext
'Ann is 22 years old.'

所以print(f'{name} is {age} years old.') 这一句中函数 print() 完成的还是它最基本的功能给它什么它就把什么输出到屏幕上

以下 print() 这个函数的官方文档

最必须读懂的部分就是这一行

print(*object, sep=' ', end='\n', file=sys.stdout, flush=False) [1]

先只注意那些有着 = 的参数sep=' 'end='\n'file=sys.stdout flush=False

这其中先关注这三个 sep=' 'end='\n'file=sys.stdout

  • sep=' '接收多个参数之后输出时分隔符号默认为空格' '
  • end='\n'输出行的末尾默认是换行符号 '\n'
  • file=sys.stdout默认的输出对象是 sys.stdout用户正在使用的屏幕)……

也就是说这个函数中有若干个具有默认值的参数即便我们在调用这个函数的时候就算没有指定它们它们也存在于此

当我们调用 print('Hello', 'world!') 的时候相当于我们调用的是 print('Hello', 'world!', sep=' ', end='\n', file=sys.stdout, flush=False)

python
import sys                                  # 如果没有这一行,代码会报错

print('Hello', 'world!')                    # 下一行的输出和这一行相同
print('Hello', 'world!', sep=' ', end='\n', file=sys.stdout, flush=False)
print('Hello', 'world!', sep='-', end='\t')
print('Hello', 'world!', sep='~')           # 上一行的末尾是 \t,所以,这一行并没有换行显示
print('Hello', 'world!', sep='\n')          # 参数之间用换行 \n 分隔
plaintext
Hello world!
Hello world!
Hello-world!	Hello~world!
Hello
world!

很多人只看各种教材教程却从来不去翻阅官方文档 —— 到最后非常吃亏只不过是多花一点点的功夫而已看过之后就会知道原来 print() 这个函数是可以往文件里写数据的只要指定 file 这个参数为一个已经打开的文件对象就可以了真的有很多人完全不知道)……

另外现在可以说清楚了

print() 这个函数的返回值是 None —— 注意它向屏幕输出的内容 print() 这个函数的返回值不是一回事

做为例子看看 print(print(1)) 这个语句 —— print() 这个函数被调用了两次第一次是 print(1)它向屏幕输出了一次完整的输出值实际上是 str(1) + '\n'而后返回一个值None而第二次调用 print(),这相当于是向屏幕输出这个 None

python
print(print(1))
plaintext
1
None

看说明书就是这样全都看了真不一定全部看懂但看总是比不看强因为总是有能看懂的部分……

关键字参数

Python 函数的参数有两种

  • 位置参数(Positional Arguments,在官方文档里常被缩写为 arg
  • 关键字参数(Keyword Arguments,在官方文档里常被缩写为 kwarg

在函数定义中带有 = 已为其设定了默认值的参数叫做 Keyword Arguments,其它的是 Positional Arguments。

在调用有 Keyword Arguments 的函数之时如若不提供这些参数那么参数在执行时启用的是它在定义的时候为那些 Keyword Arguments 所设定的默认值如若提供了这些参数的值那么参数在执行的时候启用的是接收到的相应值

比如sorted() 函数它的定义如下

sorted(iterable, *, key=None, reverse=False)

现在先只关注它的 Keyword Arguments,reverse

python
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"

sorted('abdc')
sorted('abdc', reverse=True)
plaintext
['a', 'b', 'c', 'd']
['d', 'c', 'b', 'a']

位置参数

位置参数顾名思义由位置决定其值的参数”。 divmod() 为例它的官方文档是这样写的

它接收且必须接收两个参数

  • 当你调用这个函数的时候括号里写的第一个参数是被除数第二个参数是除数 —— 此为该函数的输入
  • 而它的返回值是一个元组(Tuple,至于这是什么东西后面讲清楚),其中包括两个值第一个是商第二个是余 —— 此为该函数的输出

作为这个函数的用户”,你不能事实上也没必要调换这两个参数的意义因为根据定义被传递的值的意义就是由参数的位置决定的

python
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"

divmod(11, 3)
a, b = divmod(11, 3)
a
b

divmod(3, 11)
a, b = divmod(3, 11)
a
b
plaintext
(3, 2)
3
2
(0, 3)
0
3

可选位置参数

有些函数 pow()可选的位置参数(Optional Positional Arguments)。

于是pow() 有两种用法各有不同的结果

  • pow(x, y) —— 返回值是 x ** y
  • pow(x, y, z) —— 返回值是 x ** y % z
python
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"

pow(2, 3)
pow(2, 3, 4)
plaintext
8
0

注意 pow() 函数定义部分中圆括号内的方括号 [, z] —— 这是非常严谨的标注如果没有 z那么那个逗号 , 就是没必要的

看看 exec() 的官方文档先别管这个函数干嘛用的),注意函数定义中的两个嵌套的方括号

这些方括号的意思是说

  • 没在方括号里的 object 是不可或缺的参数调用时必须提供
  • 可以有第二个参数第二个参数会被接收为 globals
  • 在有第二个参数的情况下第三个参数会被接收为 locals
  • 但是,你没办法在不指定 globals 这个位置参数的情况下指定 locals……

可接收很多值的位置参数

再回头看看 print()它的第一个位置参数object 前面是有个星号的*object, ...

对函数的用户来说这说明这个位置可以接收很多个参数或者说这个位置可以接收一个列表或者元组)。

再仔细看看 print()它只有一个位置参数

因为位置决定了值的定义一般来说一个函数里最多只有一个这种可以接收很多值的位置参数 —— 否则如何获知谁是谁呢

如果与此同时还有若干个位置参数那么能够接收很多值的位置参数只能放置最后就好像 max() 函数那样

Class 也是函数

虽然你现在还不一定知道 Class 究竟是什么但在阅读官方文档的时候遇到一些内建函数前面写着 Class,比如 Class bool([x])千万别奇怪因为 Class 本质上来看就是一种特殊类型的函数也就是说它也是函数

python
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"

bool()
bool(3.1415926)
bool(-3.1415926)
bool(1 == 2)
bool(None)
plaintext
False
True
True
False
False

总结

本章需要大致了解的重点如下其实很简单

  • 你可以把函数当作一个产品而你自己是这个产品的用户
  • 既然你是产品的用户你要养成好习惯一定要亲自阅读产品说明书
  • 调用函数的时候注意可选位置参数的使用方法关键字参数的默认值
  • 函数定义部分注意两个符号就行了[] =
  • 所有的函数都有返回值即便它内部不指定返回值也有一个默认返回值None
  • 另外一定要耐心阅读该函数在使用的时候需要注意什么 —— 产品说明书的主要作用就在这里……

知道这些就很好了

这就好像你拿着一张地图不可能一下子掌握其中所有的细节但花几分钟搞清楚图例”(Legend)部分总是可以的知道什么样的线标示的是公交车什么样的线标示的是地铁什么样的线标示的是桥梁然后知道上北下南左西右东 —— 这之后就可以开始慢慢研究地图了……

为了学会使用 Python,你以后最常访问的页面一定是这个

对了还有就是在这一章之后你已经基本上精通 print() 这个函数的用法


脚注

(2019.02.14)[1]print() 函数的官方文档sep='' 肯定是 sep=' ' 的笔误 —— 可以用以下代码验证

python
print('a', 'b', sep='')
print('a', 'b')

(2019.03.16)有读者提醒https://github.com/selfteaching/the-craft-of-selfteaching/issues/111

而现在(2019.03.16)复制粘贴文档中的 sep=' '会发现是有空格的

这是改了么

我回去查看了一下 2019.02.13 我提交的 bug track:https://bugs.python.org/issue35986结论是人家没问题是我自己的浏览器字体设置有问题”……

然而我决定将这段文字保留在此书里以便人们看到平日里软件维护是什么样的” —— 作为一个实例放在这里很好

↑Back to Content↑