python 【第三篇】:函数及参数
函数背景
在学习函数之前,一直遵循:面向过程编程:
根据业务逻辑从上到下实现功能,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,也就是将之前实现的代码块复制到现需功能处,如下:
1 while True: 2 if cpu利用率 > 90%: 3 #发送邮件提醒 4 连接邮箱服务器 5 发送邮件 6 关闭连接 7 8 if 硬盘使用空间 > 90%: 9 #发送邮件提醒 10 连接邮箱服务器 11 发送邮件 12 关闭连接 13 14 if 内存占用 > 80%: 15 #发送邮件提醒 16 连接邮箱服务器 17 发送邮件 18 关闭连接
分析可以看出如下:
1.除了判断条件是不同之处外,所有的其他信息都是相同的。
2.能不能将这些代码归并成一个,减少重复的代码?
3.函数?
1 def 发送邮件(内容) 2 #发送邮件提醒 3 连接邮箱服务器 4 发送邮件 5 关闭连接 6 7 while True: 8 9 if cpu利用率 > 90%: 10 发送邮件('CPU报警') 11 12 if 硬盘使用空间 > 90%: 13 发送邮件('硬盘报警') 14 15 if 内存占用 > 80%:
思考如下:
1.相同之处被单独放到了一个函数里面,减少了代码量,增强了可读性。
2.是不是之后如果遇到发邮件的需求,可以直接将这个函数直接copy复用,或者调用呢?增强了复用性。
3.函数里面传了参数,参数如何用?
函数式编程和面向过程编程的区别:
- 面向过程:根据需求一行一行垒代码!代码逻辑从上往下、并且功能都是一个完了之后下一个才能执行。代码重复、不易修改重用性差!
- 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可
- 面向对象:对函数进行分类和封装,让开发“更快更好更强...”
函数的定义
函数式编程最重要的是增强代码的重用性和可读性。
1 def 函数名(参数): 2 3 ... 4 函数体 5 ...
函数的定义主要有如下要点:
- def:表示函数的关键字
- 函数名:函数的名称,日后根据函数名调用函数
- 函数体:函数中进行一系列的逻辑计算,如:发送邮件、计算出 [11,22,38,888,2]中的最大数等...
- 参数:为函数体提供数据
- 返回值:当函数执行完毕后,可以给调用者返回数据,默认返回None。
1、返回值
函数是一个功能块,该功能到底执行成功与否,需要通过返回值来告知调用者。
1 def 发送短信(): 2 3 发送短信的代码... 4 5 if 发送成功: 6 return True 7 else: 8 return False 9 10 11 while True: 12 13 # 每次执行发送短信函数,都会将返回值自动赋值给result 14 # 之后,可以根据result来写日志,或重发等操作 15 16 result = 发送短信() 17 if result == False: 18 记录日志,短信发送失败...
2.参数
参数,参数,参数,重要的事情说三遍,但是这是啥米东西?
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 复制代码 2 3 def CPU报警邮件() 4 #发送邮件提醒 5 连接邮箱服务器 6 发送邮件 7 关闭连接 8 9 def 硬盘报警邮件() 10 #发送邮件提醒 11 连接邮箱服务器 12 发送邮件 13 关闭连接 14 15 def 内存报警邮件() 16 #发送邮件提醒 17 连接邮箱服务器 18 发送邮件 19 关闭连接 20 21 while True: 22 23 if cpu利用率 > 90%: 24 CPU报警邮件() 25 26 if 硬盘使用空间 > 90%: 27 硬盘报警邮件() 28 29 if 内存占用 > 80%: 30 内存报警邮件()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def 发送邮件(邮件内容) 2 3 #发送邮件提醒 4 连接邮箱服务器 5 发送邮件 6 关闭连接 7 8 9 while True: 10 11 if cpu利用率 > 90%: 12 发送邮件("CPU报警了。") 13 14 if 硬盘使用空间 > 90%: 15 发送邮件("硬盘报警了。") 16 17 if 内存占用 > 80%: 18 发送邮件("内存报警了。")
函数中三个不同的函数:
- 普通参数
- 默认参数
- 动态参数
普通参数:
普通参数的传递并没有个数和数据类型的限制,可以传递字符串,数字,列表和字典。也不限定个数,需要注意的是:函数需要多少参数,调用的时候就要按照它定义时的顺序和数据类型传递过去。
可以是任意类型:
# ######### 定义函数 ######### # name 叫做函数func的形式参数,简称:形参 def func(name): print name # ######### 执行函数 ######### # 'test123' 叫做函数func的实际参数,简称:实参 func('test123')
默认参数:
默认参数顾名思义就是本身就带一个默认的值;
1.比如你去给人打工,中午吃饭的时候东家提供饭菜自然好,如果不提供你是不是得自己带点(可能不好吃),饿着的话肚子会不干的。
同理如果传递了这个参数,那么我们就使用传递过来的参数,如果不传递就使用默认的参数;
2.如果东家比较大方,管饭、管酒、管汤那岂不快哉,即便自己带饭也得带个黄瓜西红柿的吧,不能干吃馒头吧!
同理默认参数可以有多个,但是必须放在所有的参数后边,要不就会报错!原因是:他的参数赋值是一个一个的赋值。如果提供了默认值的形参,你默认一定要往后排序为了就是你给那些没有陪默认值的参数 !
1 def argvtest(argv1,argv2 = 'aaa',argv3 = 'bbb'): 2 print 'argv1:',argv1 3 print 'argv2:',argv2 4 print 'argv3:',argv3 5 6 argvtest('a1',argv3 = 'a2') 7 8 输出的内容: 9 argv1: a1 10 argv2: aaa 11 argv3: a2
动态参数:
动态参数一:
def func(*args) 接受多个参数,内部自动构造元组,序列前加*,避免内部构造元组。
结果:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # 4 # def f1(a): 5 # print a,type(a) 6 7 # f1(123) 8 # f1('aaa') 9 # f1([11,22,33,44]) 10 11 #动态参数一 12 def f1(*a): 13 #a = (123)单个值也会组成元祖 14 #a = (123,456)多个传入值也会组成元祖。 15 print a,type(a) 16 17 li = [1,2,3,4,5,6] 18 li1 =(77,88,99) 19 #各种类型传入,结果类型都是组成元祖 20 f1(123) 21 f1(123,456) 22 f1('aaa') 23 f1(111,'ssss',(33,44),[11,22,33,44],{'k1':1,'k2':2}) 24 25 #如果传入的是列表,或者元祖,都会被当成新元祖的元素 26 print 27 f1(li) 28 f1(li1) 29 30 #如果想输入的列表或者元祖成为单个的元素,在前面加*就会按照列表或者元祖的多个元素当参数传入 31 print 32 f1(*li) 33 f1(*li1)
结论:
1.接受多个参数
2.不管你传入什么类型的实参,最后都会组合成元祖。
3.序列前面加*,可以避免内部构造元祖
动态参数二:
def func(**kwargs) 接收多个参数,内部自动构造字典,序列前加**,直接传递字典
结果:
结论:
1.接受多个参数
2.不管你传入什么类型的实参,最后都会组合成字典。
3.序列前面加**,可以避免内部构造字典
动态参数三:
def func(*args,**kwargs):接受多个参数,既可以自动构造元组,又可以自动构造字典,传入*和**可避免内部构造元祖和字典。
结果:
代码:
1 def f2(*a,**aa): 2 print a,type(a) 3 print aa,type(aa) 4 li = [1,2,3,4,5,6] 5 li1 ={'k3':111,'k4':'aaaa'} 6 f2(11,22,33) 7 print '***********' 8 f2(k1=123,k2='aaa') 9 print '***********' 10 f2(11,22,33,k1=123,k2='aaa') 11 print '***********' 12 f2(*li,**li1)
结论:
1.这个被称为万能参数,可以接受各种类型的参数;
2.当你只传入多个元素,但不包含k-v模式,参数会被组合成元祖,字典值存在但是为空;
3.当你只传入多个元素,只包含k-v模式,参数会被组合成字典,元祖存在但是为空;
4.*参数必须在**参数前面。
局部变量和全局变量
全局变量:可以在任何地方调用。
局部变量:在对应的生成中可以被调用,比如在函数里面生成的,就只能在函数内部调用。
1 p = 'alex' #全局变量 2 def func1(): 3 #局部变量 4 a = 123 5 p = 'eric' 6 print a 7 8 def fun2(): 9 #局部变量 10 a = 456 11 print p 12 print a 13 14 func1() 15 func2()
总结:
建议规范:全局变量都大写,局部变量全小写。
1.声明在函数外面的是全局变量;
2.全局变量可以被函数调用;
3.在函数内部修改全局变量是不生效的,只是相当于又生成了一个和全局变量同名字的新局部变量,之后在函数内部调用,只会是局部变量的值生效;
4.如果想修改全局变量的值,必须得在你修改之前加一global p 这样就可以修改了。