自定义函数(上)

 

上学时我们就学过数学函数:给定数集A,对其施加一个固定法则f,得到数集B,那么f(A) = B就是一个函数关系式,简称函数。

回到Python中,目前学习、使用过的函数——你比如abs(), max(), min(), print(), len(), eval()——实际上也是对给定的对象,施加一个固定的法则,然后返回一个结果,而abs、print、max这些单词,则是该函数的名称。让我们记住这四个加粗的关键词,来学习如何自定义一个函数。

 

  • 举个栗子

Python中函数定义的一般格式为:

def <函数名称>(<对象>):
    <法则>
    return <结果>

观察上述语句,发现首先有一个def,这是英文define(定义)的缩写,在Python中专门用来定义;另外有一个return,这是Python函数中用以返回结果的命令。没太看懂没关系,来看一个栗子:

回顾本章第二节

在Python中,函数的定义被写在一个个后缀为.py的文件中。这些.py文件,被称为Python的模块(modules)。 之所以输入abs(-1)我们可以得到1这个结果,是因为Python加载了一个模块,在这个模块里,发明Python的大神已经写好了abs()遵守:当x >= 0, |x| = x;当x < 0, |x| = -x这个规则。

现在我们来自己写一个可以计算绝对值的函数。首先给这个函数取个名称,就叫做my_abs吧。想要计算绝对值,my_abs需要将绝对值计算法则施加给一个对象(设为x,当然也可以设为别的你喜欢的变量名),最后返回计算的结果。

通过学习条件、循环等章节,不难写出:

def my_abs(x):
    if x >= 0:
        return x
    else:
        return -x

现在把这个定义保存在一个.py文件中,然后按F5运行,就可以使用刚定义的函数了:

=================== RESTART: C:\Users\MSI\Desktop\demo.py ===================
>>> my_abs(-666)
666

 

  • 函数的参数

目前为止,我们使用函数已经很6了:输入函数名称、后面跟一个括号、括号内则填入函数的法则需要作用的对象——这个过程,我们称为给函数传入参数。我们在定义my_abs()时规定,该函数的法则只作用于一个对象x,因此,我们在实际使用的时候,括号内也只能传入一个参数,填0个,2个或者更多,都会报错:

=================== RESTART: C:\Users\MSI\Desktop\demo.py ===================
>>> my_abs(-666, 233)
Traceback (most recent call last):
 File "<pyshell#1>", line 1, in <module>
 my_abs(-666, 233)
TypeError: my_abs() takes 1 positional argument but 2 were given

当然,传入参数个数的限制、需要传入参数与否都取决于具体函数的定义。比如我们熟悉的print()函数,就可以用逗号分隔填入很多个参数并打印。关于函数的参数,我们会在后面更深入的学习。

 

  • IDLE工作目录

刚才我们定义my_abs()的时候,是在纯文本编辑器里面完成的。当然,定义函数的过程可以直接在IDLE的交互界面下完成:

>>> def my_abs(x):
	if x >= 0:
		return x
	else:
		return -x
#注意,函数定义写完后,要按两次回车才能退出定义语块。

	
>>> my_abs(-666)
666

优点是即写即用;缺点是写的难度有点大,中间如果输错了按了回车,就得重头写了,另外这样定义的函数不能保存,关了IDLE就没了。

不过,即便my_abs()的定义已经保存在demo.py文件中,如果我们关掉IDLE,再打开:

>>> my_abs(-666)
Traceback (most recent call last):
  File "<pyshell#19>", line 1, in 
    my_abs(-666)
NameError: name 'my_abs' is not defined

不见了耶…

之前我们讲过,要使用Python模块,首先要加载它们。试一下:

>>> import demo
Traceback (most recent call last):
 File "<pyshell#0>", line 1, in <module>
 import demo
ModuleNotFoundError: No module named 'demo'

???白写了?

其实,这是由于IDLE的默认工作目录和文件demo.py的目录不一致造成的。以我的电脑为例,IDLE默认是在安装Python时一个名为Python36-32的文件目录工作的,然鹅demo.py文件我保存在了桌面上,因此Python找不到import demo的demo模块。

解决方案也就很明确了,要么改变IDLE的工作目录,要么改变demo.py的保存位置。

在这里,不推荐大家去找自己电脑的Python36-32文件夹,因为如果不小心覆盖或者删除了里面重要的模块就不好了;IDLE的工作目录的修改,这一点我们将在之后涉及。

目前来说,我们要么在交互界面中直接定义函数使用;要么将函数保存在.py文件中运行后使用。

 

  • 封装

现在我们知道了,一个函数之所以能够实现某个功能,是因为该函数的作者对函数进行了定义。例如一个简单的计算绝对值的函数,刚才我们就写了5行代码来定义它。可想而知,更为复杂的功能其定义复杂程度也会倍增。但实际上,我们使用某个函数的时候,只需要知道他的功能是什么,而不需要搞懂其详细的定义。例如,我们知道print()能将括号中的内容打印出来,但是我们并不知道print()函数是如何定义的——这种将复杂的定义“藏”在函数定义中的过程称为封装(encapsulation)。封装的优势很多,例如用户可以直接通过调用函数来实现功能,而不需了解其详细定义;封装后的函数可以反复多次调用等等。

 

  • 本节练习

在IDLE的交互界面里面直接写一个函数average(),该函数接收两个参数,并返回二者的平均值。写完后用几组数字试验一下。

看答案

>>> def average(num_1, num_2):
	return (num_1 + num_2) / 2 #该行括号是为了优先运算括号内加法

>>> average(1, 2)
1.5
>>> average(47.8, -92)
-22.1

酱哦


 

如果还有什么问题或者发现了文章的错误,欢迎给我留言!邮箱可以随便乱写~

发表评论

邮箱地址不会被公开。 必填项已用*标注