1、自定义函数
函数执行特定的操作并返回一个值①,你可以调用它(调用时可能需要提供一些参数——放在圆括号中的内容)。一般而言,要判断某个对象是否可调用,可使用内置函数callable
函数是结构化编程的核心。那么如何定义函数呢?使用def(表示定义函数)语句
1.1 给函数编写文档
要给函数编写文档,以确保其他人能够理解,可添加注释(以#打头的内容)。还有另一种编写注释的方式,就是添加独立的字符串。在有些地方,如def语句后面(以及模块和类的开头,这将在第7章和第10章详细介绍),添加这样的字符串很有用。放在函数开头的字符串称为文档字符串(docstring),将作为函数的一部分存储起来。下面的代码演示了如何给函数添加文档字符串:
1.2 起始并不是函数的函数
数学意义上的函数总是返回根据参数计算得到的结果。在Python中,有些函数什么都不返回。在诸如Pascal等的语言中,这样的函数可能 另有其名(如过程),但在Python中,函数就是函数,即使它严格来说并非函数。什么都不返回的函数不包含return语句,或者包含return语句,但没有在return后面指定值。
2、参数魔法
2.1 值从哪里来
定义函数时,你可能心存疑虑:参数的值是怎么来的呢?通常,你不用为此操心。编写函数旨在为当前程序(甚至其他程序)提供服务,你的职责是确保它在提供的参数正确时完成任务,并在参数不对时以显而易见的方式失败
注意 在def语句中,位于函数名后面的变量通常称为形参,而调用函数时提供的值称为实参,
2.2 我能修改参数吗
函数通过参数获得了一系列的值,你能对其进行修改吗?如果这样做,结果将如何?参数不过是变量而已,行为与你预期的完全相同。在函数内部给参数赋值对外部没有任何影响。
注意 参数存储在局部作用域内
有时候,参数的排列顺序可能难以记住,尤其是参数很多时。为了简化调用工作,可指定参数的名称。
像这样使用名称指定的参数称为关键字参数,主要优点是有助于澄清各个参数的作用;虽然这样做的输入量多些,但每个参数的作用清晰明了。另外,参数的顺序错了也没关系。然而,关键字参数最大的优点在于,可以指定默认值
2.3 收集参数
有时候,允许用户提供任意数量的参数很有用。
参数前面的星号将提供的所有值都放在一个元组中,也就是将这些值收集起来。星号不会收集关键字参数,要收集关键字参数,可使用两个星号
3 作用域
变量到底是什么呢?可将其视为指向值的名称。因此,执行赋值语句x = 1后,名称x指向值1。这几乎与使用字典时一样(字典中的键指向值),只是你使用的是“看不见”的字典。实际上,这种解释已经离真相不远。有一个名为vars的内置函数,它返回这个不可见的字典:
这种“看不见的字典”称为命名空间或作用域,那么有多少个命名空间呢?除全局作用域外,每个函数调用都将创建一个。
4 递归
简单地说,递归意味着引用(这里是调用)自身
递归函数通常包含下面两部分。
基线条件(针对最小的问题):满足这种条件时函数将直接返回一个值。
递归条件:包含一个或多个调用,这些调用旨在解决问题的一部分。
这里的关键是,通过将问题分解为较小的部分,可避免递归没完没了,因为问题终将被分解成基线条件可以解决的最小问题。那么如何让函数调用自身呢?这没有看起来那么难懂。前面说过,每次调用函数时,都将为此创建一个新的命名空间。这意味着函数调用自身时,是两个不同的函数[更准确地说,是不同版本(即命名空间不同)的同一个函数]在交流。你可将此视为两个属于相同物种的动
5、小结
抽象:抽象是隐藏不必要细节的艺术。通过定义处理细节的函数,可让程序更抽象。
函数定义:函数是使用def语句定义的。函数由语句块组成,它们从外部接受值(参数),并可能返回一个或多个值(计算结果)
参数:函数通过参数(调用函数时被设置的变量)接收所需的信息。在Python中,参数有两类:位置参数和关键字参数。通过给参数指定默认值,可使其变成可选的
作用域:变量存储在作用域(也叫命名空间)中。在Python中,作用域分两大类:全局作用域和局部作用域。作用域可以嵌套。
递归:函数可调用自身,这称为递归。可使用递归完成的任何任务都可使用循环来完成,但有时使用递归函数的可读性更高
函数式编程:Python提供了一些函数式编程工具,其中包括lambda表达式以及函数map、filter和reduce