定义函数
函数是一个编程语言中必备的概念,是对一段代码的封装,提高了代码的可读性和简洁性,最重要的是你可以多次调用函数而不必关心函数的内部。我们首先来定义一个函数:
import httplib
def check_web_server(host,port,path):
h=httplib.HTTPConnection(host,port)
h.request('GET',path)
resp=h.getresponse()
print ' status=',resp.status
print ' reason=',resp.reason
print 'HTTP Headers:'
for hdr in resp.getheaders():
print '%s:%s' % hdr
return 0
这是一个访问网页的函数,def是定义函数的关键字,check_web_server 是这个函数的函数名,
host,port,path这是这个函数的形参,“:”后面这部分就是函数的实体了。return 0 代表这个函数执行到这里就退出并返回0了。暂时可以不用管函数内部的代码,现在只要了解函数的构造就可以了。
函数的参数
python有很多种定义参数的类型,极大的提高了编程的灵活性,但是初学者可能容易搞混,我们分别讲解一下函数的参数。
- 位置参数
def power(x):
return x * x
这个函数很简单,就是求x的平方并返回,此时调用power函数时,必须传入有且仅有的一个参数,此时的x就是位置参数,执行power(10),那么函数内部的x就会接收到10这个数值并返回10*10的结果为100。但是如果我们要求x的三次方,四次方,该怎么办,难道要定义2个新的函数吗。这时我们可以定义一个新的power函数:
def power(x, n):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
还是和原先一样,只不过参数变成了2个,此时调用它就需要执行:power(10,2)。那么有个问题,原来的代码因为我们修改函数而导致不能使用了,是否有别的方法使得旧的调用和新的调用兼容呢,有,这就是默认参数。
- 默认参数
def power(x, n=2):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
我们只改变了小小的一个地方,原先的n变成了n=2,这里的意思是,如果用户没有传入n的值,则n默认为2,也就是说现在调用power(10) 实质上和power(10,2)是等价的,这极大的方便了,我们调用函数,因为假设一个函数有很多参数,但是并不是很多参数都是必备的,因此可以给他设定为默认参数,这样只需要写很少的参数就能完美调用这个函数,最典型的例子比如说用户注册,需要填写用户名,邮箱,手机号,出生年月,家庭住址,等等等等,但是太多的信息输入会磨损用户的耐心,因此将用户名,邮箱,手机号设为必备参数,出生年月,家庭住址等其它不重要的信息设为默认参数就是一个很好的解决办法。另外,值得注意的是,设定的默认参数必须是不变值,比如字符串,数字,none等类型。
- 可变参数
上面的函数都是参数是固定的,那么设想如下场景,收银员结账的时候,商品的数目是不固定的,此时如果要对这个过程写个函数就需要使用可变参数。
def daily_sales_total(*all_sales):
total = 0.0
for each_sele in all_sales:
total+=float(each_sale)
return total
调用这个函数很简单,你可以将传入参数视为一个列表,以下都是合法调用:
daily_sales_total()
daily_sales_total(10)
daily_sales_total(5,10,15.0)
或者使用*将list做为参数传入:
list=[1,2,3,4]
daily_sales_total(*list)
这样就解决了上述的问题。
- 关键字参数
可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。回到最开始我们说的注册的问题,如果用户输入了几十项信息,那么我们需要设置几十项匿名参数吗?肯定有更好的解决办法:
defperson(name, age, **kw):
if'city'in kw:
print "有city参数pass"
if'job'in kw:
print "有job参数pass"
print('name:', name, 'age:', age, 'other:', kw)
此时name,age是位置次数,必须传入,而**kw为关键字参数,它会接收用户输入的其它信息:
person(‘fangqi’,22,city=’hangzhou’,job=’it’,phone=’123456’)
person(‘Jack’, 24, city=’Beijing’, addr=’Chaoyang’, zipcode=123456)
或者可以将参数以字典的形式传入:
extra = {‘city’: ‘Beijing’, ‘job’: ‘Engineer’}
person(‘Jack’,24,**extra)
- 命名关键字参数
defperson(name, age, *, city='Beijing', job)
print(name, age, city, job)
name,age为位置参数,city和job为命名关键参数,但是city定义了缺省值。定义的时候使用*分隔,后面的参数为命名关键字参数。调用的时候需要指定变量名称和值一起传入。
合法调用:
person(’fangqi’,’22’,city=’hangzhou’,job=’yunwei’)
person(’fangqi’,’22’,city,job=’yunwei’)
不合法调用:
person(’fangqi’,’22’,’hangzhou’,’yunwei’)
由于person只有2个位置参数,因此会报错。
注意:
如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了:
def person(name, age, *args, city, job):
print(name, age, args, city, job)
- 参数混合调用:
在Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用。但是请注意,参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。请自行理解下面函数的参数定义。
deff1(a, b, c=0, *args, **kw):
print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
deff2(a, b, c=0, *, d, **kw):
print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
高阶函数
所谓高阶函数就是指一个函数接受另一个函数作为参数。
比如:
def add(x, y, f):
return f(x) + f(y)
add(-5, 6, abs)
abs是系统的内置函数,求绝对值。
我们传入了abs这个参数给f是什么意思呢?f=abs 实质上是将abs函数指向了f这个变量,也就是说此时abs(-10)等价于f(-10),实际上abs也是个变量,现在只不过将这个变量的内容指向给了另一个变量f而已。
因此可以得出上述返回值为5+6=11
匿名函数
lambda函数就是我们俗称的匿名函数,匿名函数的定义顾名思义就是不需要函数名,随用随丢,多用于简单的函数计算和实现,例子如下:
a=lambda i,x:x**2/(x-i)
a(2,4)
上述代码中:i,x:x**2/(x-i) 这是整个lambda函数的实体,冒号左边i,x是函数的参数,冒号右边是函数的返回值,通常会用一句话来计算出结果,如果语句太多,那么就不建议使用匿名函数了。