函数#

前面的章节中,我们学习了如何使用条件结构来控制代码流,以及如何使用循环来消除重复的代码行。在第7课中,将学习在Python中编写函数以帮助我们执行特定任务。

一个函数是一个可重复使用的代码块,用于执行一项特定的任务。函数接收应用代码的输入,并返回代码的输出(或结果)。

input parameter –> function does something –> output results

函数可以通过模块化帮助消除重复并提高代码效率。模块化意味着代码被分成独立的单元,这些单元可以重复使用,甚至可以组合起来完成更长的任务链。

1. 模块化函数和代码#

numpy(稍后会有介绍)函数mean()为例,它从一个numpy数组中计算出平均值。

这个函数只做一件事(即计算平均值)。但是,我们可以在代码中多次使用np.mean()函数来处理多个numpy数组,因为它已经被定义为接受任何numpy数组作为输入。

num_list = [1,2,3]
#For each item in list, add 10 and print new value
for i in num_list:
    i += i
print(i)
print("mean = ",i/3)
6
mean =  2.0
import numpy as np
arr = np.array([1, 2, 3])
np.mean(arr)
2.0

np.mean()功能是模块化的,它可以很容易地与其他功能组合以完成各种任务。

2. 函数提高代码可读性的原因#

2.1 函数可以带来更好的文档#

写得好的函数可以帮助记录工作流程,因为:

  • 它们通过清楚地勾勒出输入输出而得到良好的记录。

  • 它们使用描述性的名称,帮助理解函数所执行的任务。

2.2 富有表现力的函数名称使代码具有自我描述性#

在编写函数时,我们应该用动词或清晰的标签来命名函数,以表明该函数的作用(例如,in_to_mm用于将英寸转换为毫米)。这使代码更有表现力(或自我描述),反过来,未来的自己和同事更容易阅读。

2.3 模块化代码更容易维护和编辑#

如果所有的代码都是一行一行地写的(在文件的多个部分都有重复的代码),那么维护和编辑起来就很有挑战性。

也可能在重复代码的地方重复注释。那么,如何使重复的注释保持同步?

一个因为代码改变而被误导的注释,实际上比没有注释更糟糕。

从一开始就用函数来组织代码,可以明确地记录代码所执行的任务,因为函数的所有代码和文档都包含在函数定义中。

2.4 结合测试来确保代码的正常运行#

虽然不会在本章中学习测试,但请注意,函数对测试也非常有用。

随着代码越来越长,越来越复杂,它就更容易出错。例如,如果分析依赖于经常被更新的数据,可能想在进行分析之前确保电子表格中的所有列都存在。或者,新的数据没有以不同的方式进行格式化。

如果所有代码都是由函数组成的(有内置的测试来确保它们按预期运行),那么我们可以控制函数的输入,并测试返回的输出对该输入是否正确。如果所有代码都是一行一行地重复编写,这是很难做到的。

3. 定义函数#

Python中定义一个函数需要几个组件,包括def关键字、函数名、参数(输入)和return指定函数输出的语句。

def function_name(parameter):

    some code here    
    
    return output

3.1 def 关键字和函数名#

Python中,函数定义以关键字开头,def表示新函数定义的开始,此关键字后跟函数名称,函数名是要调用函数时使用的名称(例如print()

def function_name():

3.2 输入参数#

输入参数是传递给函数以使其成功运行所需的信息。该函数将提供的值或对象作为输入参数并使用它来执行某些任务。

Python中,所需的参数在括号内提供(),如下所示:

def function_name(parameter):

也可以使用占位符变量为函数定义输入参数,例如data,它表示将在函数中执行的值或对象。

def function_name(data):

同时Python中的函数可以根据需要使用多个输入参数来定义:

def function_name(arr_1, arr_2):

3.3 return#

在Python中,函数定义需要一个返回语句来指定将由函数返回的输出

def function_name(data):
    some code here        
    return output

就像循环和条件语句一样,由函数执行的代码行,包括return语句,都在冒号后的新行中提供:并缩进一次以表示它们是函数的一部分。

return语句可以返回一个或多个值或对象,并且可以根据需要在多行代码之后完成任务(即创建将由函数返回的输出的代码)

3.4 Docstring 文档字符串#

Python中,函数还应该包含一个文档字符串,或者一个多行的文档注释,提供关于函数的细节,包括输入参数和返回的具体情况(例如对象的类型,额外的描述)以及关于如何使用该函数的任何其他重要文档。三个双引号"""后就是文档字符串的内容,Python是不会运行文档字符串的。

def function_name(data):

    """Docstrings should include a description of the function here 
    as well as identify the parameters (inputs) that the function 
    can take and the return (output) provided by the function,
    as shown below. 
    
    Parameters
    ----------
    input : type
    
        Description of input.
    
    Returns
    ------
    output : type
    
        Description of output.
    """
    some code here
    
    return output

根据以上函数的组成,写一组函数,例如

def mm_to_in(mm):

    """Convert input from millimeters to inches. 
    
    Parameters
    ----------
     mm : int or float
     
        Numeric value with units in millimeters.
    
    Returns
    ------
    output : int or float
    
        Numeric value with units in inches.
    """
    inches = mm / 25.4  
    
    return inches

mm是输入的占位符变量,inches是函数输出的占位符变量。

4. 在 Python 中调用自定义的函数#

现在我们已经定义了函数mm_to_in(),我们可以根据需要调用它来转换单位。指定了一个单值变量,在函数中用mm表示。

#Average monthly precip (mm) in Jan for Boulder, CO
precip_jan_mm = 17.78
#Convert to inches
mm_to_in(mm = precip_jan_mm)
0.7000000000000001

我们可以创建一个新变量来存储函数的输出,如下所示:

#Create new variable with converted values
precip_jan_in = mm_to_in(mm = precip_jan_mm)

precip_jan_in
0.7000000000000001

在函数之外调用这些占位符变量(例如mm或inches),就会收到错误消息。例如,下面的代码:

print(inches)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[6], line 1
----> 1 print(inches)

NameError: name 'inches' is not defined

5. 在 Python 编写具有多个参数的函数并调用#

与单个参数无太大区别,以下代码供大家参考理解

def multiply_values(x,y):

    """Calculate product of two inputs. 
    
    Parameters
    ----------
    x : int or float
    
    y : int or float

    Returns
    ------
    z : int or float
    """
    z = x * y
    
    return z
    
multiply_values(x = 0.7, y = 25.4)
17.779999999999998
precip_jan_in = 0.7

to_mm = 25.4

precip_jan_mm = multiply_values(x = precip_jan_in, y = to_mm)

precip_jan_mm
17.779999999999998