1.4 设计函数

函数是所有程序(无论是大程序还是小程序)的基本组成部分,它是我们用编程语言表达计算过程的主要媒介。到目前为止,我们已经讨论了函数的形式性质以及如何应用它们。现在我们来讨论一下什么是好的函数。从根本上说,好的函数的特性都强化了函数是抽象的概念。

  1. 每个功能都应该恰好有一个任务。 该作业应该用一个简短的名字来识别,并可以在一行文本中描述。 按顺序执行多个任务的函数应该被划分为多个函数。

  2. “不要重复自己”是软件工程的核心原则。 所谓的DRY原则是指多个代码片段不应该描述冗余逻辑。 相反,该逻辑应该实现一次,给出一个名称,然后应用多次。 如果您发现自己正在复制和粘贴一个代码块,那么您可能已经找到了实现函数抽象的机会。

  3. 函数应该是一般定义的。 Python库中没有平方,这是因为它是pow函数的一个特例,pow函数将数字取任意幂。

这些准则提高了代码的可读性,减少了错误的数量,通常还会使编写的代码的总量最小化。将一个复杂的任务分解成简洁的功能是一种需要经验才能掌握的技能。幸运的是,Python提供了几个特性来支持您的工作。

1.4.1 文档

函数定义通常包括描述函数的文档,称为docstring,它必须与函数体一起缩进。文档字符串通常使用三引号。第一行用一行描述了函数的工作。下面几行可以描述参数并阐明函数的行为:

>>> def pressure(v, t, n):
        """Compute the pressure in pascals of an ideal gas.

        Applies the ideal gas law: http://en.wikipedia.org/wiki/Ideal_gas_law

        v -- volume of gas, in cubic meters
        t -- absolute temperature in degrees kelvin
        n -- particles of gas
        """
        k = 1.38e-23  # Boltzmann's constant
        return n * k * t / v

当您以函数名作为参数调用help时,您会看到它的文档字符串(类型q以退出Python帮助)。

>>> help(pressure)

在编写Python程序时,除了最简单的函数外,所有函数都要包含文档字符串。记住,代码只写一次,但经常读很多次。Python文档包括文档字符串指导原则,以维护不同Python项目之间的一致性。

注释。在Python中,注释可以附加到#符号后面的行尾。例如,上面的注释Boltzmann’s常量描述了k。这些注释不会出现在Python的帮助中,而且它们会被解释器忽略。它们只为人类而存在。

1.4.2 默认参数值

定义一般函数的结果是引入了额外的参数。带有许多参数的函数很难调用,也很难阅读。

在Python中,我们可以为函数的实参提供默认值。当调用该函数时,带有默认值的参数是可选的。如果没有提供它们,则将默认值绑定到形式参数名。例如,如果一个应用程序通常计算一摩尔粒子的压力,这个值可以作为默认值提供:

>>> def pressure(v, t, n=6.022e23):
        """Compute the pressure in pascals of an ideal gas.

        v -- volume of gas, in cubic meters
        t -- absolute temperature in degrees kelvin
        n -- particles of gas (default: one mole)
        """
        k = 1.38e-23  # Boltzmann's constant
        return n * k * t / v

在本例中,=符号表示两种不同的含义,这取决于使用它的上下文。在def语句头中,=不执行赋值,而是指示在调用压力函数时使用的默认值。相比之下,函数体中对k的赋值语句将名称k绑定到Boltzmann常数的近似值上。

>>> pressure(1, 273.15)
2269.974834
>>> pressure(1, 273.15, 3 * 6.022e23)
6809.924502

pressure函数被定义为接受三个参数,但是在上面的第一个调用表达式中只提供了两个参数。在本例中,n的值取自def语句default。如果提供第三个参数,则忽略默认值。

作为一个准则,函数体中使用的大多数数据值都应该表示为指定参数的默认值,这样它们就很容易检查,并且可以被函数调用者更改。一些永远不变的值,例如基本常数k,可以绑定在函数体或全局框架中。

Last updated

Was this helpful?