函数
函数,这个词我们应该都不陌生,在初等数学里面,它是指与自变量符合某种关系的对应的值,在高等数学里面,它是指一个集合符合某种准则映射出来的对应集合,不管怎么说,实际上都是一种“有始有终”的样子,我们每给出一个对象,经过一定的处理之后得到最终的对象。
在Python里面,函数也指成为一段代码的表示,它是一段具有特定功能的、可以重用的语句组,它也是一种功能的抽象,一般函数都表达特定功能。
我们使用函数最根本的原因无非是:
- 1.让我们的一段代码能够重新利用,在处理相同的问题时可以直接调用,大大提高我们的编程效率。
- 2.让我们的代码结构更加清晰,当你设置的每个函数都负责独自的模块的时候,程序结构会更让我们清晰,在出现bug的时候也更容易处理。
函数的定义
在Python中,函数的定义基本格式如下:
def <函数名>(<参数>) :
<函数体>
return <返回值>
在函数定义的时候首先使用def
保留字声明,后面是你定义的函数的名字及参数,后面还有个:
不要忘了,下面是你的函数体,用来完成你需要这个函数完成的功能,最后是返回值,它是指当前函数运行之后的你要返回的结果,使用return
保留字声明,值得注意的是,在一个函数的定义中,返回值是可有可无的,你定义的函数可以拥有返回值,也可以没有返回值,示例如下:
#这是一段爬虫的小代码,有返回值:
def gethtmltext(url):
try:
r = requests.get(url)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
return print('爬取有误')
#这是一个没有返回值的小代码:
def wait(a):
print('程序暂停中,请等待{}秒钟...'.format(a))
time.sleep(a)
return #注意,既然没有返回值,此处的ruturn可有可无
在每个函数被定义之后,如果这个函数没有被调用,那么它是不会被程序执行的,只有被调用,函数才会被执行。函数只是一段完整的代码的封装,它向我们提供一个接口,每当调用它的时候它会自动执行它需要完成的功能。
函数的调用
- 那么函数如何被调用呢?很简单,你只需要引用已定义函数的函数名及其参数即可完成函数的调用,当然,有一些函数没有参数(参数的使用方法后文会有介绍),不过在调用的时候函数名后的括号是不能少的。对于有参数的函数调用过程,是该函数将你调用时使用的实际参数转变为函数内部使用的形式参数后执行完其所要完成的功能,然后返回一个所谓的返回值。另外,在调用的时候,对于参数的调用有两种方法:
#如调用上文中的wait()函数,使程序休眠5秒钟
#method one
>>> wait(5)
#method two
>>> wait(a=5)
也就是说,在调用的时候可以直接给出参数的实际值,或者精确的指明参数给其赋值,这在只有一个参数的时候使用效果不明显,当有多个参数的时候,精确的给每个参数赋值可以避免造成使用混乱,因为在精确赋值的时候是不需要考虑参数的位置顺序的。
函数的参数
在定义函数的时候,是否需要参数是可选项,也就是说参数是可有可无的,但是不管有没有参数,都必须要保留函数名后边的括号。
如:
#没有参数的函数定义
def putwords():
print('emmmm')
return 'emmmm'
#调用
>>> putwords()
emmmm
>>> A
'emmmm'
事实上,在定义的函数的时候,你可以选择包含参数和不包含参数,而包含参数又包括非可选参数、可选参数和可变参数。其定义方式如下:
def <函数名>(<非可选参数>,<可选参数>,<可变参数>):
<函数体>
return <返回值>
需要注意的是,在Python中定义函数的时候,可选参数一定要在非可选参数的后面。
那么三种参数的区别是什么呢?如何定义呢?
- 实际上,非可选参数指的就是一个变量,而可选参数指的是事先已经被我们给赋值后的变量,至于可变参数,是在变量的前面加个
*
号,声明其为可变参数。示例如下:
def f(a,b=1,*c):
<函数体>
return <返回值>
在示例当中,a、b、c分别为非可选参数、可选参数、可变参数。那么怎么理解呢?也就是说,在你调用这个函数f
的时候,一定要给出a的值,如果没有给出a的值程序会报错的,而对于b,事实上它也一定需要值来运行程序,不过在定义的时候我们已经给定了初始值为1,也就是说如果我们在调用函数的时候给定了值,那么程序将会按照我们给定的值运行,如果我们调用的时候忽略了这个选项,那么程序将会按照默认值1运行程序,并不会出现错误。而对于可变参数c,它实际上就是不确定总数量的参数,理解起来可能比较抽象,不过看下面这个例子:
def f(a,b=1,*c):
for i in c:
<函数体>
return <返回值>
可以看到,在定义的函数f
中存在一个遍历结构,而被遍历的对象是c,那么这样就好理解了,假如我们如下调用此函数:
#这里采用精确赋值的方法给出参数
>>> f(a=1,b=2,1,2,3)
#或者这样调用
>>> f(a=1,1,2,3,4,5) #这里没有赋值给b,那么它就是默认值1
根据两次调用参数的不同,参数中的c分别指1、2、3以及1、2、3、4、5,那么函数体执行的次数也就分别为3次和5次了。
函数的返回值
函数的返回值往往在函数最后,需要用保留字return
来声明,不过前文已经说过,一个函数可以有返回值,也可以没有返回值,另外,有返回值的时候又可以有多个返回值。
看一个示例:
#定义一个函数,求给定参数的和
>>> def sum(*x): #参数设为可变参数
sum = 0
for i in x: #遍历参数
sum+=i
if sum<0:
return sum #如果和小于0,则只返回和
else:
return sum-1,sum,sum+1 #否则返回三个值
当你调用上边的程序是,如果求得的和不小于0,那么返回的是三个值,而它们之间是由逗号隔开的,证明它们是一个元组结构,既然是一个元组类型,那么你就可以按照元组类型的操作对这个返回值进行你想要的操作。当然你可以在返回值那里加上小括号,但实际上无需如此,因为辨别一个数据类型是否为元组的核心特征是各元素之间的逗号。这里多加一句,如果你想要复习一下Python里面的数据类型,可以看一下我之前的一篇博客:《元组、列表、字典、集合详细介绍说明》。
局部变量和全局变量
首先,关于局部变量和全局变量,我们需要知道的是它们是不同的变量,即使有些时候它们的变量名称完全相同,但它们之间也不存在任何关系。局部变量,顾名思义就是只在某个局部地方存在的变量,在Python中,在函数内部使用的变量为局部变量。示例如下:
>>> n=15
>>> m=20
>>> def maxnum(a,b):
n=a
m=b
if n<m:
return m
elif n==m:
return m,n
else:
return n
>>> A = maxnum(1,2)
>>> A
2
>>> n
15
>>> m
20
在上例中,函数外部的值分别为15、20的n、m为全局变量,而函数maxnum
中的n和m为局部变量,两者间互不影响,在调用这个函数的时候程序按照函数内n、m分别被赋值为1、2来执行,当程序执行完毕,函数内部的变量n、m立即被释放掉,就不复存在了。
当然,我们也可以将函数体内部的局部变量来变成全局变量,只需要使用global
保留字即可,示例如下:
>>> n=15
>>> m=20
>>> def maxnum(a,b):
global n=a
global m=b
if n<m:
return m
elif n==m:
return m,n
else:
return n
>>> A = maxnum(1,2)
>>> A
2
>>> n
1
>>> m
2
可以看到,当声明函数内部的变量n、m为全局变量后,在调用函数后,其值也随着函数内部处理变成了相应的结果。
不过注意,如果函数内部的局部变量为组合数据类型的话,且未对其进行新创建,那么此组合数据类型就相当于全局变量,示例如下:
>>> alist = ['c','k'] #创建一个组合数据类型的列表
>>> def f(a):
alist.append(a)
>>> f('n')
>>> alist
['c','k','n']
#而如果是下面这样的话:
>>> alist = ['c','k']
>>> def f(a):
alist = ['c']
alist.append(a)
>>> f('n')
>>> alist
['c','k']
由上边这个例子可以很清楚的捋清上面那句话的关系。
那么总结一下:
- 对于基本数据类型,局部变量和全局变量完全不相关。
- 对于组合数据类型,如果局部变量未在函数内部重新创建,则其是全局变量。
lambda函数
lambda函数是一种匿名函数,也就是没有名字的函数,它使用lambda
保留字定义,定义格式如下:
<函数名> = lambda <参数>:<表达式>
实际上,它等价于使用def
定义的函数,只不过它是一种紧凑表达形式,只在一行内就将函数体给覆盖下来,所不同的一点是,它的函数体只能是表达式。如下一个定义:
#定义一个lambda表达式,有两个参数x1,x2
>>> fx = lambda x1,x2 : x1**2+x2**3
#调用
>>> fx(2,2)
12
#定义一个lambda表达式,无参数
>>> f = lambda : '我是一个lambda表达式'
#调用
>>> f()
'我是一个lambda表达式'
经过这个例子我们大致能理解它的基本使用。不过对于lambda函数而言,它主要用作一些特定函数或方法的参数进行使用,在很多地方都能看到提醒:谨慎使用lambda函数,建议使用def
定义的函数,虽然它足够简洁,但是其实却也容易造成混乱,关于它,我们不再深究,def
定义的函数已经足够好,熟练掌握即可。
总结
本篇文章主要介绍了Python中函数的一些基本定义方法使用方法等基础知识,不过这些基础知识已经足够我们掌握它了,更深层次是需要能熟练的利用它们,这离不开更多的、更大量的其它知识储备,加油!