人海茫茫
相识真好

决战Python之巅(十)

前言

昨天将函数前半部分看完了,这里稍微做一下总结。

知识回顾

函数定义

函数的定义很简单,如下:

函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需要调用这个函数名即可

注意:调用函数名之后,要在函数名后面加一对(),函数才会执行,否则将返回函数的内存地址。
在代码中定义一个函数:

def  calc(x,y):
	res = x**y
	return res

那为什么要使用函数呢?
在学习函数之前,假设需要你写一段代码,7*24h监控公司服务器,当CPU/MEMORY/DISK超过阈值时报警并发送邮件,那你可能会这么写:
决战Python之巅(十)
乍一看这段代码能够将功能实现,但你会发现,这中间有很多重复的代码,而且万一哪天想换个报警的方式,还得换三次。这时候你学到了函数,那你可能会这么写:

def send_mail():
	#发送邮件提醒
	连接邮箱服务器
	发送邮件
	关闭连接

while True:
	if cpu利用率>90%
		send_mail()
	if 硬盘使用空间>90%:
		send_mail()
	if 内存占用>90%:
		send_mail()

相比较一下,函数的特性变可得出:

  • 减少重复的代码
  • 是代码变得可拓展,易维护

函数的参数

这时候又有一个新的需求,就是每次调用这个发邮件函数的时候,我可能要发给不一样的人来维护,比如CPU占用率的报警我要发给Eric,硬盘使用率要发给Rain,内存使用率要发给Kris,这可怎么办呢?
之前我们写的函数里面只能发给特定的人的邮箱…唔,想一想,我们之前好像已经学过变量,那我们如果将邮箱账号换成变量,然后每次调用函数的时候给变量赋我们需要的值便可。如我们之前定义过的calc():

def  calc(x,y):
	res = x**y
	return res

这里定义时括号里的x,y便是形参变量,形参变量只有在被调用时才会被分配内存单元,在调用结束后就会被立刻释放内存单元。因此,形参只在函数内部有效。函数调用结束后就不能再使用该函数的形参变量。
而当我们在调用这个calc()函数时,是一定要给两个参数的,即:

calc(3,4)

a=5
b=6
calc(a,b)

这里使用的3,4或者a,b,称为实参变量。实参可以是常亮、变量、表达式、函数等,无论是哪种类型,在进行函数调用时,必须有明确的值,以便来传送给形参。
决战Python之巅(十)

位置参数

在运行上面的代码时可以发现,a的值总是传给了x,b的值总是传给了y,如果我们给a,b换个位置,执行:

c = calc(b,a)

就会得到另一个结果,并且是b**a,这就意味着这一次b的值给了x,而a的值给了y,这样以位置顺序确定对应关系的参数就叫位置参数

关键参数

如果有一天你不想按顺序传参数了,你可以使用关键字参数,又称关键参数。你只需要做的只是指定参数名,就是告诉函数你的这个值是给谁的。

def stu_info(name,age,country,course)
	print('姓名:',name)
	print('年龄:',age)
	print('国籍:',country)
	print('课程:',course)

# 关键参数
stu_info('山炮',course='Python',age=22,country='CN')

#但绝不可以这样
stu_info('山炮',course='Python',22,country='CN')
#这样也不行,同一个参数传两个值
stu_info('山炮',25,age=22,country='CN')

注意:关键参数要放在位置参数后面,切记。

默认参数

当我们在调用上面的函数录入学生信息时,我们发现由于学生大部分都是中国学生,所以国籍country这个形参我们传的大部分都是CN,为了简便,我们可以将contry变成默认参数,即这个参数在调用时不指定,那么就是你定义的默认值,如果指定了,就用你指定的值。这时,我们就可以这么定义参数:

def stu_info(name,age,course,country = 'CN')
	print('姓名:',name)
	print('年龄:',age)
	print('课程:',course)
	print('国籍:',country)

#调用函数
stu_info('山炮',22,'Python')   # 这里使用默认国籍CN
stu_info('松岛菜菜子',22,'TV','JP')  # 这里使用指定的值

你可能注意到了,在把country变成默认参数后,同时把它移动到了最后面,可以思考下为什么?


很简单…
不放在最后会产生歧义。
还是上面的例子…

# 假设我这么定义,注意这是错误的
def stu_info(name,age,country = 'CN',course)
	print('姓名:',name)
	print('年龄:',age)
	print('课程:',course)
	print('国籍:',country)
# country使用默认值,course = 'Python'
stu_info('山炮二号',25,'Python')

运行后会报错,前两个没什么问题,到了第三个这里,’Python’原本你是想传给course,但是由于位置的关系,它会传给country,而最后一个course就没有值传给它,它又不是个默认参数,所以会报错。…其实根本就不能运行,因为定义函数的时候就错了- –

非固定参数

还是回到最开始发邮件的那个函数,我们已经可以做到给不同的人发邮件,只要定义的时候多加一个参数user:

def send_mail(user):
	#发送邮件提醒
	连接邮箱服务器
	发送邮件给user
	关闭连接

现在你的公司扩招了,负责CPU处理的人变多了,这时候你想给他们都发邮件,那你的做法可能是:

for i in users_list:
	send_mail(i)

循环给他们每个人发邮件…那如果我现在要求只给一部分的人发邮件,不要全部,你可能会想到去改users_list,假如这个list里有成千上万人,就是很多很多人,你要给其中一部分发邮件,那修改list的方法似乎有点难以实现…当你不确定你的用户个数时,你需要定义非固定参数

def send_mail(*args):
	#发送邮件提醒
	连接邮箱服务器
	发送邮件给user
	关闭连接

…一般我们在定义非固定参数时,都用 *args ,当然不用args也可以,但主要是为了规范。
这里定义的参数就是非固定参数,当你调用参数时:

#调用参数
send_mail('Alex','Rain','Eric','Kris')

*args会将你传给它的值变为一个元组形式,即('Alex','Rain','Eric','Kris'),然后会将元组中的每个元素依次传出,相当于for循环了这个元组,但是不需要另外写代码,只要定义时注意将参数定义成非固定参数即可。
这样就实现了可传入不确定个数的参数

非固定关键字参数

和上面的非固定参数差不多,只不过这里定义时是使用两个*,即**kwargs,这里传入值时,需要使用关键字参数传入的形式:

def send_mail(**kwargs):
	#发送邮件提醒
	连接邮箱服务器
	发送邮件给user
	关闭连接

#调用参数
send_mail(name='Alex',age=22,sex='male')

**kwargs会将传给它的参数转成dict,则上面代码调用函数的效果就是返回{‘name’:‘Alex’,‘age’:22,‘sex’:‘male’}。

函数的返回值

这里来处理一个历史遗留问题,在上面我们定义calc函数时,你会发现函数的最后有一句:return res如果函数外部的代码想要获得函数执行的结果,就需要通过return来返回结果。
注意:

  • 函数执行过程中只要遇到return语句,就会停止执行返回测试结果。可以理解为第一句return即为函数的结束。
def func():  # 可以思考下执行这个函数会打印2嘛?
	print('1')
	return True
	print('2')
	return False
  • 如果函数中未指定return的内容,变会返回None

局部变量

我们知道了函数定义时可以定义各种变量,但这些变量都有一个限制,就是他们只能在这个函数中使用,在其他函数中想要调用是不行的。即局部变量的作用域是定义该变量的函数。

作用域(scope),程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。

而与之相对的则是全局变量。

全局变量

在程序一开始定义的变量称为全局变量。全局变量的作用域是整个程序,你在程序重定义的函数也可以调用全局变量。

全局变量vs局部变量

决战Python之巅(十)

  • 全局变量的作用域是整个框即整个程序,而局部变量的作用域仅限于定义该变量的函数的作用域。
  • 当全局变量与局部变量重名时,在定义该局部变量的函数中,局部变量起作用,其他地方全局变量起作用。
    决战Python之巅(十)

嵌套函数

嵌套函数就是在一个函数中再定义一个函数:

a = 3
b = 4
def fun1():
	print(a)
	def func2():
		print(b)
	#func1 里调用func2
	func2()

#调用func1()
func1()

这个调用的结果就是:3,4
再看这段代码:
决战Python之巅(十)
请问最后输出的是什么?


决战Python之巅(十)
牢记局部变量的作用域。

匿名函数

匿名函数就是不需要指定显示的函数名
决战Python之巅(十)
匿名函数最多支持我们之前学过的三元函数。
主要用处是与其他的函数搭配使用。
决战Python之巅(十)

高阶函数

变量可以指向函数,函数的参数可以接受变量,那么一个函数就可以接受另一个函数作为参数,这种函数就叫高阶函数。
决战Python之巅(十)
只需要满足以下任一条件,即为高阶函数:

  • 接受一个或者多个函数作为输入
  • return返回另一个函数
赞(0) 打赏
未经允许不得转载:老康的学习空间 » 决战Python之巅(十)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏