说明:
使用函数可以使程序实现功能模块化,大大简洁我们的程序,这里主要讨论Python中函数的下列内容:
1
2
3
4
5
6
7
|
1 .函数定义与函数参数
2 .局部变量和全局变量
3 .函数默认参数和关键参数
4 .*args和**kwargs
5 .函数返回值 return 与yield简单说明
6 .lambda函数(匿名函数)
7 .Python内置函数
|
因为函数部分内容跟C语言中的很多内容都十分相似,所以会结合C语言来进行对比学习。
1.函数定义与函数参数
--基本格式1:不参参数
·定义:
1
2
|
def sayHi():
print "Hello!"
|
·调用:
--基本格式2:带一个参数
·定义:
1
2
|
def sayHi(name):
print "Hello, %s, how are you?" % name
|
·调用:
1
2
|
>>> sayHi( 'xpleaf' )
Hello, xpleaf, how are you?
|
--基本格式3:多个参数
·定义:
1
2
3
|
def sayHi(name, age):
print "Hello, %s, how are you?" % name
print "You are %s years old." % age
|
·调用:
1
2
3
|
>>> sayHi( 'CL' , 20 )
Hello, CL, how are you?
You are 20 years old.
|
2.局部变量与全局变量
·看下面一个程序:
1
2
3
4
5
6
7
8
9
10
|
#!/usr/bin/env python
age = 29
def sayHi():
age = 28
print "function age:%s" % age
sayHi()
print "gloable age:" ,age
|
·执行结果如下:
1
2
3
|
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day3$ python fun3.py
function age: 28
gloable age: 29
|
·Python函数中,作用域的概念与C语言中是一样的,这里不再提及;
·有两点需要注意:
a.通过局部变量改变全局变量,可以在函数中使用global,如下代码:
1
2
3
4
|
def sayHi():
global age
age = 28
print "function age:%s" % age
|
b.全局变量没有定义,在函数中使用global定义,相当于定义全局变量,但不建议这样使用;
4.函数默认参数和关键参数
--函数默认参数
·看下面一个程序:
1
2
3
4
5
6
7
8
9
10
|
#!/usr/bin/env python
def users(username, group = 'GDUT' ):
mydict = {}
mydict[username] = group
return mydict
print "default argument:" , users( 'xpleaf' ) # use default argument
print "full argument:" , users( 'xpleaf' , 'BAT' ) # do not use default argument
|
·执行结果如下:
1
2
3
|
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day3$ python default .py
default argument: { 'xpleaf' : 'GDUT' }
full argument: { 'xpleaf' : 'BAT' }
|
·定义函数时,参数默认赋值,在使用函数时即可以不对此类参数赋值,即为默认参数;
·使用默认参数的原则:定义函数时,非默认参数在前,默认参数在后;
·如下面即是非法的情况:
1
2
3
4
5
6
7
8
9
10
11
|
#!/usr/bin/env python
def users(group = 'GDUT' , name):
mydict = {}
mydict[username] = group
return mydict
print "default argument:" , users( 'xpleaf' ) # use default argument
#编译器将无法知道 'xpleaf' 是赋给group变量还是name变量
print "full argument:" , users( 'xpleaf' , 'BAT' ) # do not use default argument
|
·执行时提示错误:non-default argument follows default argument
1
2
3
4
|
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day3$ python default .py
File "default.py" , line 3
def users(group = 'GDUT' , name):
SyntaxError: non- default argument follows default argument
|
--函数关键参数
·在使用多个默认参数的函数中,如下程序:
1
2
3
4
5
6
7
8
9
|
#!/usr/bin/env python
def users(name, age, group = 'GDUT' , project = 'Python' ):
print '' 'name:%s
age:%s
group:%s
project:%s '' ' % (name, age, group ,project)
users( 'xpleaf' , 21 )
|
·执行结果如下:
1
2
3
4
5
|
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day3$ python default .py
name:xpleaf
age: 21
group:GDUT
project:Python
|
-只指定第一个默认参数
·对应的users的代码修改为:
1
|
users( 'xpleaf' , 21 , 'BAT' )
|
·执行结果如下:
1
2
3
4
5
|
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day3$ python default .py
name:xpleaf
age: 21
group:BAT
project:Python
|
-同时指定两个默认参数
·对应的users的代码修改为:
1
|
users( 'xpleaf' , 21 , 'BAT' , 'stupy' )
|
·执行结果如下:
1
2
3
4
5
|
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day3$ python default .py
name:xpleaf
age: 21
group:BAT
project:stupy
|
-只需要指定第二个默认参数
·对应的users的代码修改为:
1
|
users( 'xpleaf' , 21 , project = 'stupy' )
|
·执行结果如下:
1
2
3
4
5
|
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day3$ python default .py
name:xpleaf
age: 21
group:GDUT
project:stupy
|
·指定第二个参数,此即为关键参数,可以不按原来参数的顺序(不指定关键参数则达不到目的);
·也可以指定多个默认参数,从而不按原来参数的位置,users代码修改如下:
1
|
users(project = 'stupy' , name = 'xpleaf' , age = 21 , group = 'BAT' )
|
·执行结果如下:
1
2
3
4
5
|
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day3$ python default .py
name:xpleaf
age: 21
group:BAT
project:stupy
|
-更清晰的例子
·程序代码如下:
1
2
3
4
5
6
7
8
|
#!/usr/bin/env python
def func(a, b= 5 , c= 10 ):
print 'a=%s, b=%s, c=%s' % (a, b, c)
func( 3 , 7 )
func( 25 ,c= 24 )
func(c= 50 , a= 100 )
|
·执行结果如下:
1
2
3
|
func( 3 , 7 ) # a = 3 , b= 7 ,c= 10
func( 25 , c= 24 ) # a= 25 , b= 5 ,c= 24
func(c= 50 , a= 100 ) # a= 100 ,b= 5 ,c= 50
|
4.*args和**kwargs
·在参数不确定的情况下使用*args和**kwargs,前者可以输出参数对应的元组,后者可以输出参数对应的字典;
·*args演示如下:
a.程序代码
1
2
3
|
def sayHI(*args):
print args
sayHI( 'xpleaf' , 21 , 'GDUT' )
|
b.执行结果
1
2
|
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day3$ python fun2.py
( 'xpleaf' , 21 , 'GDUT' )
|
·**kwargs演示如下:
a.程序代码
1
2
3
4
5
|
def sayHi2(**kwargs):
print kwargs
sayHi2(name = 'xpleaf' , age= 21 , phone = 5201314 )
|
b.执行结果
1
2
|
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day3$ python fun2.py
{ 'phone' : 5201314 , 'age' : 21 , 'name' : 'xpleaf' }
|
·由于字典是没有次序的,所以输出的顺序会跟输入的不同;
·由于kwargs是以字典的方式获取函数中的参数,这也意味前,如果原来函数就没有参数,而且在使用函数时又没有使用关键字参数的方式执行函数,是会有问题的:
1
2
3
4
5
6
7
|
>>> sayHi2( 'xpleaf' , age = 21 , phone = 5201314 )
Traceback (most recent call last):
File "<stdin>" , line 1 , in <module>
TypeError: sayHi2() takes exactly 0 arguments ( 3 given)
>>> sayHi2(name = 'xpleaf' , age = 21 , phone = 5201314 )
{ 'phone' : 5201314 , 'age' : 21 , 'name' : 'xpleaf' }
|
·如果只按照上面的写法,则说明可以不加任何参数,当然,根据此思路,我们也可以定义如def sayHi(name,age,**kwargs)等形式的;
·关于该函数参数的说明,更详细的,可以参考廖雪峰老师的相关文档,也是写得非常详细的。
·*args和**kwargs同时使用:
1
2
3
4
|
>>> def func( * args, * * kwargs):
... print "args is:" , args
... print "kwargs is:" , kwargs
...
|
·演示如下:
1
2
3
4
5
6
7
|
>>> func(name = "xpleaf" , age = 22 , hobby = "Python" )
args is : ()
kwargs is : { 'hobby' : 'Python' , 'age' : 22 , 'name' : 'xpleaf' }
>>> func( "cl" , name = "xpleaf" , age = 22 , hobby = "Python" )
args is : ( 'cl' ,)
kwargs is : { 'hobby' : 'Python' , 'age' : 22 , 'name' : 'xpleaf' }
|
·需要说明的时,由于*args参数在前,**kwargs参数在后,所以在执行函数时应该要按照这个顺序填写参数,否则会报错:
1
2
3
|
>>> func(name = "xpleaf" , age = 22 , hobby = "Python" , "clyyh" )
File "<stdin>" , line 1
SyntaxError: non - keyword arg after keyword arg
|
5.函数返回值return与yield简单说明
--return说明
·在函数中添加return语句可以返回函数执行的某些值,但会造成阻塞问题,看下面代码:
1
2
3
4
5
|
def func():
for i in range( 10 ):
return i
result = func()
print result
|
·执行结果如下:
1
2
|
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day3/blog$ python func.py
0
|
·与C语言类似,函数遇到return即会结束,意味着使用return返回函数值会造成阻塞问题,即不能每执行一次循环,返回一个值,再执行其他操作,然后再去执行函数中的循环;
·可以使用yield来代替return实现上面功能;
--yield说明
-代码改写1
·上面代码改写为:
1
2
3
4
5
6
7
8
|
import time
def func():
for i in range( 10 ):
time.sleep( 1 )
yield 'Loop' , i
result = func()
print result
|
·执行结果如下:
1
2
|
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day3/blog$ python func.py
<generator object func at 0x7f06d4300c80 >
|
·由前面迭代器的知识,yield实现的就是创建一个迭代器;
-代码改写2
·上面代码改写为:
1
2
3
4
5
6
7
8
9
10
11
12
|
import time
def func():
for i in range( 10 ):
time.sleep( 1 )
yield 'Loop' , i
result = func()
print result.next()
print result.next()
print result.next()
print result.next()
print result.next()
|
·执行结果如下:
1
2
3
4
5
6
|
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day3/blog$ python func.py
( 'Loop' , 0 )
( 'Loop' , 1 )
( 'Loop' , 2 )
( 'Loop' , 3 )
( 'Loop' , 4 )
|
·只调用了5次迭代器,因此只产生5个值;
-代码改写3
·上面代码改写为:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
import time
def func():
for i in range( 10 ):
time.sleep( 1 )
yield 'Loop' , i
result = func()
print result.next()
print 'Upon:No.1'
print result.next()
print 'Upon:No.2'
print result.next()
print 'Upon:No.3'
print result.next()
print 'Upon:No.4'
print result.next()
print 'Upon:No.5'
print 'None'
|
·执行结果如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day3/blog$ python func.py
( 'Loop' , 0 )
Upon:No. 1
( 'Loop' , 1 )
Upon:No. 2
( 'Loop' , 2 )
Upon:No. 3
( 'Loop' , 3 )
Upon:No. 4
( 'Loop' , 4 )
Upon:No. 5
None
|
·即可以实现前面[跳出函数-->再执行其它操作-->再回到函数]的功能;
·注意事项为:
a.用了yield就不能使用return,用了yield就表示用了迭代器
b.yield要用在函数中,不能直接在循环中写,即在不是函数内的循环中写,如:
1
2
3
|
for i in range( 10 ):
time.sleep( 1 )
yield 'Loop' , i
|
6.lambda函数(匿名函数)
--关于匿名函数的说明
1
2
3
4
5
6
7
8
9
10
11
12
|
lambda 函数也叫匿名函数,即,函数没有具体的名称。先来看一个最简单例子:
def f(x):
return x * * 2
print f( 4 )
Python中使用 lambda 的话,写成这样
g = lambda x : x * * 2
print g( 4 )
那么, lambda 表达式有什么用处呢?很多人提出了质疑, lambda 和普通的函数相比,就是省去了函数名称而已,同时这样的匿名函数,又不能共享在别的地方调用。其实说的没错, lambda 在Python这种动态的语言中确实没有起到什么惊天动地的作用,因为有很多别的方法能够代替 lambda 。同时,使用 lambda 的写法有时显得并没有那么pythonic。甚至有人提出之后的Python版本要取消 lambda 。
回过头来想想,Python中的 lambda 真的没有用武之地吗?其实不是的,至少我能想到的点,主要有:
1. 使用Python写一些执行脚本时,使用 lambda 可以省去定义函数的过程,让代码更加精简。
2. 对于一些抽象的,不会别的地方再复用的函数,有时候给函数起个名字也是个难题,使用 lambda 不需要考虑命名的问题。
3. 使用 lambda 在某些时候让代码更容易理解。
|
--lambda函数应用1:定义简单函数
·演示如下:
1
2
3
|
>>> g = lambda x:x** 2
>>> g( 4 )
16
|
·关于lambda函数与普通函数的简单区别:
a.lambda执行操作时,第一次是引用变量,即引用匿名函数,往后相同操作是引用上一次的指针:
1
2
3
4
5
6
7
|
>>> g = lambda x:x** 2
>>> g( 4 )
16
>>> g( 4 )
16 #直接引用上一次结果的指针
>>> g( 6 )
36 #新的操作,会重新引用变量
|
b.普通函数无论是否执行相同操作,都是直接调用函数的功能;
--lambda函数应用2:应用于map函数
·查看map函数的帮助文档:
1
2
3
|
map(...)
map( function , sequence[, sequence, ...]) -> list
#即前面第一个参数可以为一个函数,并将sequence交给该函数处理,这时可使用lambda函数
|
·演示如下:
1
2
3
4
5
6
7
8
|
>>> a = range( 10 )
>>> b = range( 10 )
>>> a,b
([ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ], [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ])
>>> map(lambda x:x** 2 ,a) #定义 1 个参数
[ 0 , 1 , 4 , 9 , 16 , 25 , 36 , 49 , 64 , 81 ]
>>> map(lambda x,y:x**y,a,b) #定义两个参数
[ 1 , 1 , 4 , 27 , 256 , 3125 , 46656 , 823543 , 16777216 , 387420489 ]
|
--lambda函数应用3:应用于sorted()排序
·sorted()可对数据类型进行排序,虽然字典无序,但可以有序输出字典中的内容;
·演示如下:
1
2
3
4
5
|
>>> a = { 2 : 'a' , 4 : 'f' , 8 : 'c' , 9 : 'e' }
>>> a
{ 8 : 'c' , 9 : 'e' , 2 : 'a' , 4 : 'f' }
>>> sorted(a.items())
[( 2 , 'a' ), ( 4 , 'f' ), ( 8 , 'c' ), ( 9 , 'e' )]
|
·通过sorted()结合lambda函数可以选取基于字典中key值或value值的排序:
1
2
3
4
|
>>> sorted(a.items(),key=lambda x:x[ 0 ]) #基于key值排序
[( 2 , 'a' ), ( 4 , 'f' ), ( 8 , 'c' ), ( 9 , 'e' )]
>>> sorted(a.items(),key=lambda x:x[ 1 ]) #基于value值排序
[( 2 , 'a' ), ( 8 , 'c' ), ( 9 , 'e' ), ( 4 , 'f' )]
|
·sorted()中的key并非特指字典中的key值,这是sorted()函数中的参数关键字:
1
2
|
sorted(...)
sorted(iterable, cmp=None, key=None, reverse=False) --> new sorted list
|
7.Python内置函数
·Python中内置函数比较多,这里不给出,参考个人的内置函数文档即可,往后学习更深入,内置函数使用更多时会再重新写一篇专门Python内置函数的文章。
时间: 2024-09-17 07:00:46