第四章 python中的函数

时间:2023-01-01 11:57:53
第一节 函数的介绍 
1)函数就是完成特定功能的一个语句组,这组语句作为一个单位使用,并且给它取一个名字。
2)可以通过函数名在程序的不同地方多次执行(这通常叫做函数调用),却不需要在所有地方都重复编写这些语句。 
3)自定义函数 
    - 用户自己编写的 
4)预定义的python函数 
    - 系统自带的一些函数,还有一些第三方编写的函数,如其他程序员编写的一些函数,对于这些现成的函数用户可以直接拿来使用。 
5)为什么使用函数 
6)降低编程的难度 
    - 通常将一个复杂的大问题分解成一系列更简单的小问题,然后将小问题继续划分成更小的问题,当问题细化为足够简单时,我们就可以分而治之。这时,我们可以使用函数来处理特定的问题,各个小问题解决了,大问题也就迎刃而解了。 
7)代码重用 
    - 我们定义的函数可以在一个程序的多个位置使用,也可以用于多个程序。此外,我们还可以把函数放到一个模块*其他程序员使用,同时,我们也可以使用其他程序员定义的函数。这就避免了重复劳动,提供了工作效率。 
8)函数的定义和调用 
9)当我们自己定义一个函数时,通常使用def语句,其语法形式如下所示: 
def 函数名(参数列表) : #可以没有参数 
        函数体 
  1 #!/usr/bin/python 
  2 
  3 def fun(x,y):        #形参 
  4     print "i get a :",x 
  5      
  6 s = raw_input("input somthing:") 
  7 
  8 fun(s,'other')        #实参 
在python中如何显示中文: 
  1 #!/usr/bin/python 
  2 #coding:utf8        我们可以在linux系统中使用这段代码
  3 def fun(x,y): 
  4     if x == y: 
  5         print x,"=",y 
  6     else: 
  7         print x,"!=我",y 
  8 
  9 s1 = raw_input("input somthing:") 
 10 s2 = raw_input("input somthing:") 
 11 
 12 fun(s1,s2) 

网上我们有时候也可以看到下面几种不同的写法: 
#coding=utf8
#encoding:utf8
#encoding=utf8 
#_*_ coding:utf8  _*_ 

  1 #!/usr/bin/python 
  2 #coding:utf8 
  3 def fun(x,y): 
  4     if x == y: 
  5         print x,"=",y 
  6     else: 
  7         print x,"!=",y 
  8 缺省参数(默认参数) 
  9 def machine(y,x=3):        这里在给形式参数赋值的时候是从右向左的 
 10     print "生成一个",x,'元',y,'口味的冰激凌!' 
 11 
 12 #s1 = raw_input("input somthing:") 
 13 #s2 = raw_input("input somthing:") 
 14 
 15 #fun(s1,s2) 
 16 
 17 machine('巧克力') 

局部变量和全局变量 
    - Python中的任何变量都有其特定的作用域 
    - 在函数中定义的变量一般只能在该函数内部使用,这些只能定义的特定部分使用的变量我们称之为局部变量; 
    - 在一个文件顶部定义的变量可以供该文件中的任何函数调用,这些可以为整个程序所使用的变量称为全局变量 
  1 #!/usr/bin/python 
  2 
  3 a = 100        全局变量         
  4 
  5 def fun(): 
  6     print a 
  7      
  8 fun() 
  9 
 10 #!/usr/bin/python 
 11        
 12    
 13 def fun(): 
 14     a = 100     局部变量 
 15     print a 
 16                      
 17 fun() 
在函数内部全局变量的声明 
  1 #!/usr/bin/python 
  2 
  3 a = 100 
  4 
  5 def fun(): 
  6     x = 100 
  7     global y        这里声明全局变量 
  8     y = 200 
  9     print a 
 10 
 11 fun() 

下面这两种的输出x的值是不相同的,如果fun()函数部执行则按照上一个输出结果,如果运行了,则相当于给x重新赋值 
注:    a.global语句 
                    global 变量名 
            b.强制声明为全局变量 

第二节    函数返回值 
    - 函数被调用后会返回一个指定的值 
    - 函数调用后默认返回None 
    - return 返回值 
    - 返回值可以是任意类型 
    - return执行后,函数终止 
    - 区分返回值和打印 
>>> def f(x): 
...     print x 
... 
>>> f(0) 

>>> def f(x,y): 
...     print x+y 
... 
>>> f(2,3) 

>>> z = f(2,3)        这里并没有将求和以后的值赋值给z,因为函数没有设置返回值,默认的返5回值为空,即None,在下面我们使用print取打印z的时候就会看到 
>>> z 
>>> print z 
None 
>>> sum([1,2,3,4,5])     sum函数是一个求和函数,它的返回值是所有元素的和
15 
>>> z = sum([1,2,3,4,5])        这里我们将这个值赋给z后,我们会看到z的输出结果
>>> z 
15 
如果我们也想用自定义函数实现此功能,我们就要使用return,下面我们给出一个例子 
>>> def f(x,y): 
...     print "welcome !!" 
...     return x+y 
... 
>>> f(2,3) 
welcome !! 
>>> z = f(2,3) 
welcome !! 
>>> z 

返回值我们不一定要定义成数字,我们也可以定义成一个字符串,或一个列表等 
>>> def f(): 
...     return "hello" 
... 
>>> f() 
'hello' 
>>> def f(): 
...     return range(10) 
... 
>>> f() 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
>>> def f():        如果在函数中定义两个return的时候,他只会返回第一次执行的return,结束
...     return "one" 
...     return "two" 
... 
>>> f() 
'one' 
>>> def f(x,y):        我们再来定义一个例子说明一下缩进的效果 
...     if x>y: 
...             return -1 
...     print "hello world"        这里如果上面的条件不满足直接输出hello 
...                                             hello world 
>>> f(2,3)                         
hello world 
>>> z = f(2,3)            我们又一次看到了上面的结果 
hello world 
>>> z 
>>> print z 
None 

第三节    函数的其他传参 
1)向函数传元组和字典 
2)处理多余实参 
>>> def f(x): 
...     print x 
... 
>>> f(10) 
10 
>>> f('hello') 
hello 
>>> f([1,2,3,4]) 
[1, 2, 3, 4] 
>>> f(range(10)) 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
>>> l = range(10) 
>>> f(l) 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
>>> f(('a','b')) 
('a', 'b') 
>>> f({1:111,2:222,3:333}) 
{1: 111, 2: 222, 3: 333} 
下面我们定义一个字符串的输出格式: 
>>> def f(x,y):         
...     print "%s : %s" % x,y 
... 
>>> print "%s : %s" % ('name','milo') 
name : milo 
下面我们可以看一下如何将一个元组给它传进去: 
>>> t = ('name','milo') 
>>> def f(x,y): 
...     print "%s : %s" % (x,y) 
... 
>>> f(*t)        使用一个*号就代表我们要传进去的这个值t是一个元组
name : milo 
下面我们来定义一个含有默认值的函数,我们在传参的时候,要使用字典进行传参 
>>> def f(name="name",age=0): 
...     print "name: %s" % name 
...     print "age: %s" % age 
... 
>>> d = {'age':30,'name':'milo'}        这里字典是无序的 
>>> f(**d)        两个 *号就代表这是一个字典 
name: milo 
age: 30 
>>> d['age']=31        当字典中的值改变的时候,我们不需要考虑函数里面的值是如何变化的 
>>> d 
{'age': 31, 'name': 'milo'} 
>>> f(**d) 
name: milo 
age: 31 
我们在调用函数的时候,如果使用字典,字典的key必须和函数的key相同,如果不相同,就会报错: 
>>> d={'a':30,'n':'milo'} 
>>> f(**d) 
Traceback (most recent call last): 
  File "<stdin>", line 1, in <module> 
TypeError: f() got an unexpected keyword argument 'a' 
>>> f(d['n'],d['a'])            我们只有这样才能实现调用 
name: milo 
age: 30 
总结: 
向函数传元组和字典 
    fun(*args) 
    fun(**kwords) 
如果我们在调用函数的时候如果它只需要一个参数,而我们在传递的时候传递了多个参数,这时,我们就需要一个方法: 

第四节    冗余参数处理: 
    处理多余实参 
    def fun(*args,**kw) 
例子: 
>>> def f(x):        我们在定义函数的时候这样定义我们一次只能传递一个值 
...     print x 
... 
>>> f(1) 

>>> def f(x,*args):        我们要想在输入的时候输入多个值,不出现报错,我们就可以采用这种形式 
...     print x 
...     print args 
... 
>>> f(1) 

()                我们可以看到在输出的时候,当我们输入的是一个值的时候,元组为空 
>>> f(1,2,3,4)        当我们输入的是多个值的时候,后面的所有的值都会被定义到元组中去 

(2, 3, 4)            我们也可以在函数中不要输出这个元组 
下面是以字典形式存放多余的数值 
>>> def f(x,*args,**kwargs): 
...     print x 
...     print args 
...     print kwargs 
... 
>>> f(1) 

() 
{} 
>>> f(1,2,3,4,5,6) 

(2, 3, 4, 5, 6) 
{} 
>>> f(x=1,y=2) 

() 
{'y': 2} 
>>> f(1,2,3,4,5,y=20,z=30)      下面我们就看到了在传值的时候,他会默认的处理元组,字典 

(2, 3, 4, 5) 
{'y': 20, 'z': 30} 

第五节    匿名函数:lambda 
匿名函数 
    - lambda函数是一种快速定义单行的最小函数,是从Lisp借用来的,可以用在任何需要函数的地方。 
例子: 
>>> def f(x,y): 
...     return x*y 
... 
>>> g = lambda x,y:x*y        这里我们不需要使用def来定义函数,可以使用lambda匿名函数后面是定义两个参数x ,y,然后求他们的成绩操作 
>>> f(2,3) 

>>> g(2,3)            这里的效果是和f()函数相同的 

1)使用Python写一些执行脚本时,使用lambda可以省去定义函数的过程,让代码更加精简。 
2)对于一些抽象的,不会别的地方再复用的函数,有时候给函数起个名字也是个难题,使用lambda不需要考虑命名的问题。 
3)使用lambda在某些时候让代码更容易理解。 

lambda基础: 
1)lambda语句中,冒号前面是参数,可以有多个,用逗号隔开,冒号右边的返回值。 
lambda语句构建的其实是一个函数对象:
>>> g = lambda x,y:x*y 
>>> g 
<function <lambda> at 0x7fb1213715f0> 
>>> lambda x,y:x*y 
<function <lambda> at 0x7fb121371668>        我们可以看到这两个值是相同的 

lambda应用实例 
1)reduce为逐次操作list里的每项,接收的参数为2个,最后返回的为一个结果 
>>> def myadd(x,y): 
...     return x+y 
... 
>>> sum=reduce(myadd,(1,2,3))        这里我们可以理解为像递归一样 
>>> sum 

下面我们使用reduce()这个函数,实现函数的递归调用 
>>> l=range(1,6) 
>>> l 
[1, 2, 3, 4, 5] 
>>> def f(x,y): 
...     return x*y 
... 
>>> reduce(f,l)            这里我们做一下说明:reduce(函数,序列)
120 
上述函数我们是做成绩的,reduce每次是取两个值,将前一次计算的结果返回给x,接下来再在后面的序列中取一个值进行计算。 
>>> f = lambda x,y:x*y        我们使用匿名函数实现,结果是一样的 
>>> reduce(f,l) 
120 
>>> reduce(lambda x,y:x*y,l)        对于上面的这几条语句我们也可以一条搞定,就不需要 
120                                                   重新定义f这样一个变量了

第六节    switch语句 
1)switch语句用于编写多分支结构的程序,类似与if...elif...else语句。 
2)switch语句表达的分支结构比if...elif..else语句表达的更清晰,代码的可读性更高。 

3)但是python并没有提供switch语句 
4)python可以通过字典实现switch语句的功能。 
5)实现方法分为两步。 
    - 首先,定义一个字典。 
    - 其次,调用字典的get()获取相应的表达式。 
5)通过字典调用函数 
6){1:case1,2:case2}.get{x,lambda *arg,**key:}() 
下面我们做一个计算器: 
代码: 
  1 #!/usr/bin/python 
  2 #coding:utf-8 
  3 
  4 from __future__ import division        注意这里我们引入了一个模块 
  5 
  6 def add(x,y): 
  7     return x+y 
  8 
  9 def jian(x,y): 
 10     return x-y 
 11 
 12 def cheng(x,y): 
 13     return x*y 
 14 
 15 def chu(x,y): 
 16     return x/y 
 17 
 18 def operator(x,o,y): 
 19     if o == "+": 
 20         print add(x,y) 
 21     elif o == "-": 
 22         print jian(x,y) 
 23     elif o == "*": 
 24         print cheng(x,y) 
 25     elif o == "/": 
 26         print chu(x,y) 
 27     else: 
 28         pass 
 29 
 30 operator(2,'+',4) 
 31 operator(2,'-',4) 
 32 operator(2,'*',4) 
 33 operator(2,'/',4) 
hy@hy:~/Documents/py$ python 14.py 

-2 

0.5 
我们可以看到他的执行效果和switch应该是相同的 
  1 #!/usr/bin/python 
  2 #coding:utf-8 
  3 
  4 from __future__ import division 
  5 
  6 def add(x,y): 
  7     return x+y 
  8 
  9 def jian(x,y): 
 10     return x-y 
 11 
 12 def cheng(x,y): 
 13     return x*y 
 14 
 15 def chu(x,y): 
 16     return x/y 
 17 
 18 operator={"+":add,"-":jian,"*":cheng,"/":chu} 
 19 
 20 def f(x,o,y):         
 21     print operator.get(o)(x,y)        通过这个函数功能我们就可以实现如同switch的作用 
 22 f(3,"+",2) 
下面我们来使用更简单的程序: 
  1 #!/usr/bin/python 
  2 # _*_ coding:utf-8 _*_ 
  3 
  4 from __future__ import division 
  5 x=1 
  6 y=2 
  7 operator = raw_input()        这里我们可以手动输入,当然x和y我们也可以实现手动输入
  8 result = { 
  9     "+":x+y, 
 10     "-":x-y, 
 11     "*":x*y, 
 12     "/":x/y 
 13 } 
 14 print result.get(operator) 

第七节    内置函数 
首先通过一个案例来讲解 
1)返回数字绝对值 
2)取列表最大最小值 
  1 #!/usr/bin/python 
  2 def a(x): 
  3     if x < 0: 
  4         return -x 
  5     return x 
  6 
  7 n = a(-10) 
  8 
  9 print n 
上面写的是一个取绝对值的函数 
绝对值,最大最小值 
    abs() 
    max() 
    min() 
>>> abs(-10) 
10 
>>> l = [1,2,3,45,23,4,5] 
>>> max(l) 
45 
>>> min(l) 

>>> len(l)        求l列表的元素个数

>>> divmod(5,2)            求5除以2的商,及余数    
(2, 1)                商和余数 
>>> pow(2,3) 

>>> pow(2,3,3)        相当于(2^3)%3 

>>> callable(min)        测试所要调用的语句是不是一个函数 
True 
>>> f=100 
>>> callable(f)            如果不是一个函数,则返回False
False 
>>> def f(): 
...     pass 
... 
>>> callable(f)        如果是函数则返回True
True 
下面我们了解一下isinstance()函数的作用,它是用来判断某个对象的类型是什么,比如下面l是一个列表: 
>>> l             
[1, 2, 3, 45, 23, 4, 5] 
>>> type(l) 
<type 'list'> 
>>> type([]) 
<type 'list'> 
>>> if type(l) == type([]): 
...     print 'ok' 
... 
ok 
>>> isinstance(l,list) 
True 
>>> isinstance(l,int) 
False 
>>> cmp("hello","hello")        用来比较大小的,如果前面的和后面的相等则返回0 

>>> cmp("h","hello")                前面小于后面返回-1 
-1 
>>> cmp("hzzzzzz","hello")    前面大于后面返回1 
1                                                 

hex(number)    -> string        将一个整形或长整形转换成十六进制 
oct()            将一个整形或长整形的数转换成八进制 
chr()            将一个在大于等于0,小于256的数转换成一个字符串 

与类型相关的内置函数: 
str.capitalize()        字符串首字母大写函数 
str.replace()            字符串替换函数 
str.split()                  字符串切割函数 
 
>>> s='hello'         
>>> s.capitalize()           将字符串的首字母变成大写 
'Hello' 
>>> s.replace('hello','good')        将字符串里面的hello替换成good
'good' 
>>> ss='123123123'             
>>> ss.replace('1','x')            将字符串里面的1替换成x
'x23x23x23'     
>>> ss.replace('1','x',1)            将字符串里面的从头开始1替换依次 
'x23123123'     
>>> ss.replace('1','x',2)            替换两次 
'x23x23123' 
>>> ss.replace('1','x',3)            替换三次 
'x23x23x23' 
>>> ip="192.168.1.123" 
>>> ip.split('.')            这里split起到了一个切割的作用,将里面的数字提取出来,然后返回值   
['192', '168', '1', '123']    是一个列表 
>>> ip.split('.',1)            指定分割一次 
['192', '168.1.123'] 
>>> ip.split('.',2)            指定分割两次 
['192', '168', '1.123'] 
>>> ip.split('.',3)            指定分割三次 
['192', '168', '1', '123'] 
>>> import string                也可以先引入一个模块 
>>> string.replace(s,'hello','good') 
'good' 
序列处理函数 
filter() 
zip() 
map() 
reduce() 
   

>>> def f(x): 
...     if x>5: 
...             return True 
... 
>>> f(10) 
True 
>>> f(3) 
>>> l = range(10) 
>>> l 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
>>> filter(f,l)            filter的功能是当函数f返回值为True的时候,它会把列表里面的相应的值保 
[6, 7, 8, 9]                留下来(f函数,作用于l列表)
 
>>> name=['milo','zou','tom'] 
>>> age=[20,30,40] 
>>> tel=['133','156','189'] 
>>> zip(name,age,tel)               在这里zip实现的功能是并行遍历
[('milo', 20, '133'), ('zou', 30, '156'), ('tom', 40, '189')] 
>>> 
>>> map(None,name,age,tel)          我们也可以使用map来遍历列表
[('milo', 20, '133'), ('zou', 30, '156'), ('tom', 40, '189')] 
>>> zip(name,age,tel) 
[('milo', 20, '133'), ('zou', 30, '156'), ('tom', 40, '189')] 
>>> test=[1,2]               我们新定义一个列表 
>>> zip(name,age,tel,test)     在这里使用zip并行遍历的时候,我们会发现他会以最短的列表
[('milo', 20, '133', 1), ('zou', 30, '156', 2)]     元素个数为列的个数标准输出 
>>> map(None,name,age,tel,test) 
[('milo', 20, '133', 1), ('zou', 30, '156', 2), ('tom', 40, '189', None)]
注意:我们在使用map并行遍历的时候,它会先将原先的列表的元素个数计算一下,然后以元素个数多的为列输出,如果其他短的部分则使用None补上。 
map他不但可以进行并行遍历,还可以做一些并行的操作,比如我们下面的乘法运算 
>>> a=[1,3,5] 
>>> b=[2,4,6] 
>>> def mf(x,y): 
...     return x*y 
... 
>>> map(None,a,b) 
[(1, 2), (3, 4), (5, 6)] 
>>> map(mf,a,b) 
[2, 12, 30] 
>>> l=range(1,101)            下面我们定义一个1-100的序列 
>>> l 
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100] 
>>> def rf(x,y): 
...     return x+y 
... 
>>> reduce(rf,l)        使用reduce对其进行递归求和操作
5050 
>>> reduce(lambda x,y:x+y,l)            这里我们使用了lambda这个匿名函数
5050 
>>> filter(lambda x:x%2 == 0,l)        使用filter过滤出所有的偶数
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100] 
 
>>> foo=[2,18,9,22,17,24,8,12,27]
>>> print filter(lambda x:x%3 == 0,foo) 
[18, 9, 24, 12, 27] 
>>> print map(lambda x:x*2+10,foo) 
[14, 46, 28, 54, 44, 58, 26, 34, 64] 
map的例子,可以写成: 
>>> print [x*2+10 for x in foo] 
[14, 46, 28, 54, 44, 58, 26, 34, 64] 
非常简洁,易懂。filter的例子可以写成: 
>>> print [x for x in foo if x%3 ==0] 
[18, 9, 24, 12, 27] 

第八节    模块和包 
1)模块是python组织代码的基本方式。 
2)python的脚本都是用扩展名为py的文本文件保存的,一个脚本可以单独运行,也可以导入另一个脚本中运行。当脚本被导入运行时,我们将其称为模块(module)。 
3)模块名与脚本的文件名相同 
    - 例如我们编写了一个名为items.py的脚本,则可在另外一个脚本中用import Iterms语句来导入它。 
4)python的模块可以按目录组织为包 
5)创建一个包的步骤是: 
    - 建立一个名字为名字的文件夹, 
    - 在该文件夹下创建一个__init__.py文件, 
    - 根据需要在该文件夹下存放脚本文件、已编译扩展及子包。 
    - import pack.m1,pack.m2,pack.m3 
下面我们使用导入包的操作: 
hy@hy:~/Documents/py$ cat cal.py 
#!/usr/bin/python 
#coding:utf-8 

from __future__ import division 

def add(x,y): 
    return x+y 

def jian(x,y): 
    return x-y 

def cheng(x,y): 
    return x*y 

def chu(x,y): 
    return x/y 

def operator(x,o,y): 
    if o == "+": 
        print add(x,y) 
    elif o == "-": 
        print jian(x,y) 
    elif o == "*": 
        print cheng(x,y) 
    elif o == "/": 
        print chu(x,y) 
    else: 
        pass 

operator(2,'/',4) 
hy@hy:~/Documents/py$ python cal.py 
0.5 
hy@hy:~/Documents/py$ cat new.py  在new.py这个文件中我们导入之前定义的cal.py这个包
import cal 
hy@hy:~/Documents/py$ python new.py         在执行他的时候可以达到同样的效果 
0.5 
如果我们想要调用cal这个模块中的一个函数,我们可以使用一下方法: 
new.py 
  1 import cal 
  2 
  3 cal.add(1,2) 
hy@hy:~/Documents/py$ cat new.py         我们还可以将这个值打印出来 
import cal 

a = cal.add(1,2) 
print a 
hy@hy:~/Documents/py$ python new.py 
0.5 
hy@hy:~/Documents$ ls   我们要将多个文件存在的目录当成一个包,在包内添加__init__.py 
py                                          这里我们是指py这个包 
hy@hy:~/Documents$ cat test.py        我们还需要在这个包的外面加入这个包所对应的模块 
import py.cal 
print py.cal.add(1,2) 
hy@hy:~/Documents$ python test.py 
0.5 

hy@hy:~/Documents/py$ python
>>> from cal import add 
>>> add(2,3) 

总结: 
1)模块是一个可以导入的python脚本文件; 
2)包是一堆按目录组织的模块和子包,目录下的__init__.py文件存放了包的信息; 
3)可以用import,import as,from import等语句导入模块和包。