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.参数

参数,参数,参数,重要的事情说三遍,但是这是啥米东西?

 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         内存报警邮件()
无参数示例
 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) 接受多个参数,内部自动构造元组,序列前加*,避免内部构造元组。

结果:

 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实例

结论:

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 这样就可以修改了。

posted @ 2015-12-12 23:39  楚时邀月  阅读(234)  评论(0编辑  收藏  举报