jiabanl 发表于 2015-12-15 10:57:19

第四章 python中的函数

第一节 函数的介绍

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)
0
>>> def f(x,y):
...   print x+y
...
>>> f(2,3)
5

>>> z = f(2,3)      这里并没有将求和以后的值赋值给z,因为函数没有设置返回值,默认的返5回值为空,即None,在下面我们使用print取打印z的时候就会看到 >>> z
>>> print z
None

>>> sum()   sum函数是一个求和函数,它的返回值是所有元素的和15

>>> z = sum()      这里我们将这个值赋给z后,我们会看到z的输出结果>>> z

15

如果我们也想用自定义函数实现此功能,我们就要使用return,下面我们给出一个例子 >>> def f(x,y):
...   print "welcome !!"
...   return x+y

...

>>> f(2,3)
welcome !!
5 >>> z = f(2,3)
welcome !!
>>> z
5

返回值我们不一定要定义成数字,我们也可以定义成一个字符串,或一个列表等

>>> def f():
...   return "hello"
...
>>> f()
'hello'
>>> def f():
...   return range(10)
...
>>> f()


>>> 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()

>>> f(range(10))

>>> l = range(10)
>>> f(l)

>>> 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 "", line 1, in
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)
1
>>> def f(x,*args):      我们要想在输入的时候输入多个值,不出现报错,我们就可以采用这种形式
...   print x
...   print args
...
>>> f(1)
1
()                我们可以看到在输出的时候,当我们输入的是一个值的时候,元组为空
>>> f(1,2,3,4)      当我们输入的是多个值的时候,后面的所有的值都会被定义到元组中去
1
(2, 3, 4)            我们也可以在函数中不要输出这个元组

下面是以字典形式存放多余的数值

>>> def f(x,*args,**kwargs):
...   print x
...   print args
...   print kwargs
...
>>> f(1)
1
()
{}
>>> f(1,2,3,4,5,6)
1
(2, 3, 4, 5, 6)
{}
>>> f(x=1,y=2)
1
()
{'y': 2}
>>> f(1,2,3,4,5,y=20,z=30)      下面我们就看到了在传值的时候,他会默认的处理元组,字典
1
(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)
6
>>> g(2,3)            这里的效果是和f()函数相同的
6

1)使用Python写一些执行脚本时,使用lambda可以省去定义函数的过程,让代码更加精简。

2)对于一些抽象的,不会别的地方再复用的函数,有时候给函数起个名字也是个难题,使用lambda不需要考虑命名的问题。

3)使用lambda在某些时候让代码更容易理解。



lambda基础:

1)lambda语句中,冒号前面是参数,可以有多个,用逗号隔开,冒号右边的返回值。

lambda语句构建的其实是一个函数对象:>>> g = lambda x,y:x*y
>>> g

>>> lambda x,y:x*y

      我们可以看到这两个值是相同的



lambda应用实例

1)reduce为逐次操作list里的每项,接收的参数为2个,最后返回的为一个结果

>>> def myadd(x,y):
...   return x+y
...
>>> sum=reduce(myadd,(1,2,3))      这里我们可以理解为像递归一样
>>> sum

6

下面我们使用reduce()这个函数,实现函数的递归调用 >>> l=range(1,6)
>>> l

>>> 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
6
-2
8
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 =
>>> max(l)
45
>>> min(l)
1

>>> len(l)      求l列表的元素个数7
>>> divmod(5,2)            求5除以2的商,及余数   

(2, 1)                商和余数

>>> pow(2,3)
8
>>> pow(2,3,3)      相当于(2^3)%3
2
>>> callable(min)      测试所要调用的语句是不是一个函数
True
>>> f=100

>>> callable(f)            如果不是一个函数,则返回FalseFalse
>>> def f():
...   pass
...

>>> callable(f)      如果是函数则返回True
True

下面我们了解一下isinstance()函数的作用,它是用来判断某个对象的类型是什么,比如下面l是一个列表: >>> l            

>>> type(l)



>>> type([])
>>> if type(l) == type([]):
...   print 'ok'
...
ok
>>> isinstance(l,list)
True
>>> isinstance(l,int)
False
>>> cmp("hello","hello")      用来比较大小的,如果前面的和后面的相等则返回0
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


>>> filter(f,l)            filter的功能是当函数f返回值为True的时候,它会把列表里面的相应的值保

                留下来(f函数,作用于l列表)

>>> name=['milo','zou','tom']
>>> age=
>>> 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=               我们新定义一个列表

>>> 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=
>>> b=
>>> def mf(x,y):
...   return x*y
... >>> map(None,a,b)
[(1, 2), (3, 4), (5, 6)]
>>> map(mf,a,b)



>>> l=range(1,101)            下面我们定义一个1-100的序列
>>> l
>>> 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过滤出所有的偶数



>>> foo=>>> print filter(lambda x:x%3 == 0,foo)

>>> print map(lambda x:x*2+10,foo)



map的例子,可以写成: >>> print



非常简洁,易懂。filter的例子可以写成: >>> print




第八节    模块和包
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
3
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

3

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

总结:

1)模块是一个可以导入的python脚本文件;

2)包是一堆按目录组织的模块和子包,目录下的__init__.py文件存放了包的信息;

3)可以用import,import as,from import等语句导入模块和包。
页: [1]
查看完整版本: 第四章 python中的函数