标签:
函数是对程序逻辑进行结构化或过程化的一种编程方法。能将整块代码巧妙地隔离成易于管理的小块,这样在以后的python开发中十分重要,可以使你的程序更加简洁,有逻辑,可读性强。
一.函数的调用
Python内置了很多有用的函数,我们可以直接调用。要调用一个函数,需要知道函数的名称和参数,比如求绝对值的函数abs,只有一个参数。可以在交互式环境中用help()查看关于调用函数的相关信息
>>> abs(100)100
>>> help(abs)
Help on built-in function abs in module __builtin__:
abs(...)
abs(number) -> number
Return the absolute value of the argument.
Python中已经有很多非常实用的函数,如果应用的好,可以大大提高效率。
二.定义函数
那么现在一定有小伙伴要问,我们能不能定义自己想要的函数?当然可以。
在Python中,定义一个函数要使用def语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回。
我们以自定义一个求绝对值的myabs函数为例:
def my_abs(x):
if x >= 0:
return x
else:
return -x
大家可以自己试验一下代码。请注意:
1.Python的缩进规则。
2.函数体内部的语句在执行时,一旦执行到return时,函数就执行完毕,并将结果返回。因此,函数内部通过条件判断和循环可以实现非常复杂的逻辑。如果没有return语句,函数执行完毕后也会返回结果,只是结果为None。
Python函数返回值 有两种形式: 1 返回一个值。 2 返回多个值。
现看看 返回一个值 的:
>>>def firstvalue(a,b):
c = a + b
return c>>> print firstvalue(1,2)3
再看看 返回多个值 的:
>>>def secondvalue(a,b):
c = a + b
return (a,b,c)>>> x,y,z = secondvalue(1,2)>>> print ’x=’,x,’y=’,y,’z=’,z
x= 1 y= 2 z= 3
三.函数的参数
Python的函数定义非常简单,但灵活度却非常大。除了正常定义的必选参数外,还可以使用默认参数、可变参数和关键字参数,使得函数定义出来的接口,不但能处理复杂的参数,还可以简化调用者的代码。
默认参数
我们来举一个例子。比如现在我们想要计算x的立方。接着上一节的内容,我们使用多参数函数:
>>>def power(x, n):
s = 1
while n > 0:
n = n - 1
s = s * x
return s>>> power(5, 2)25>>> power(5, 3)125
这个函数可以计算任意数的n次方。但是请读者试一试输入power(5)你会发现报错,这是因为你只输入了一个参数。
但是如果我们经常使用的只是计算x的立方,为了简化输入,我们可以这样:
>>>def power(x, n=3):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
这样,当我们调用power(5)时,相当于调用power(5, 2):
从上面的例子可以看出,默认参数可以简化函数的调用。设置默认参数时,有几点要注意:
一 是必选参数在前,默认参数在后,否则Python的解释器会报错(思考一下为什么默认参数不能放在必选参数前面);
二 是如何设置默认参数。当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数。
>>> def func(a,b=7,c=10):... print a,b,c
...>>> func(2)2 7 10>>> func(2,b=5)2 5 10>>> func(2,c=6)2 7 6
其中默认参数有一些坑,提示:(默认参数一定要用不可变对象,如果是可变对象,运行会有逻辑错误!比如不能把默认参数定义为可变的list)虽然有办法解决但还是尽量避免。
可变参数
在Python函数中,还可以定义可变参数。顾名思义,可变参数就是传入的参数个数是可变的,可以是1个、2个到任意个,还可以是0个。
比如我们计算a平方 + b平方 + c平方 + ……。
def calc(numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
这是想要计算需要把numbers定义成一个list或tuple,才能使用for in循环把list中的数字调用出来用于计算。
>>> calc([1, 2, 3])14>>> calc((1, 3, 5, 7))84
为了简化这一步,我们使用可变参数。定义可变参数和定义list或tuple参数相比,仅仅在参数前面加了一个*号。在函数内部,参数numbers接收到的是一个tuple,因此,函数代码完全不变。但是,调用该函数时,可以传入任意个参数,包括0个参数:
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
这是只需要输入calc(1,2,3)即可。
如果已经有一个list或者tuple,要调用一个可变参数怎么办?可以这样做:
>>> nums = [1, 2, 3]>>> calc(nums[0], nums[1], nums[2])14
这种写法当然是可行的,问题是太繁琐,所以Python允许你在list或tuple前面加一个*号,把list或tuple的元素变成可变参数传进去:
>>> nums = [1, 2, 3]>>> calc(*nums)14
这种写法相当有用,而且很常见。可见*可以把元素变为可变参数从而可以更灵活的使用。
还有其他的参数如 关键字参数 ,和有这几种参数一起使用而得到的 组合参数 。这些就不详细介绍了。(感觉没咋用啊)
比如我们给个组合参数的例子,我们使用默认参数和可变参数:
def func(a, b, c=0, *args):
print ’a =’, a, ’b =’, b, ’c =’, c, ’args =’, args>>> func(1, 2)
a = 1 b = 2 c = 0 args = ()>>> func(1, 2, c=3)
a = 1 b = 2 c = 3 args = ()>>> func(1,2,3,’a’,’b’)
a = 1 b = 2 c = 3 args = (’a’, ’b’)
四.几种高阶函数的使用
这一部分可能内容比较复杂,所以我们重点讲解几个用以处理list的高阶函数,来体会Python中函数的意义。Python是一门非常强大的语言,其中有很多功能就7体现在对函数的抽象应用之中。其中变量可以指向函数,函数的参数能接收变量,比如:
>>> def f(x):
return x+1
>>> a=f>>> a(2)3
那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
一个最简单的高阶函数:
def add(x, y, f):
return f(x) + f(y)
>>> add(-2,-9,abs)
#令a=-2,b=-9,f=abs 11
现在我们可以看出Python中函数是十分抽象的。接下来介绍几种常用的高阶函数。
map
map()函数接收两个参数,一个是函数,一个是序列,map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回。所以map是处理序列的有力工具之一。
来个例子:
>>> def add(x):... return x+100... >>> a = [11,22,33]>>> map(add,a)
[111, 122, 133]
即实现了让一个list中所有元素都加上100的操作,同理可以定义别的函数或者使用Python的自带函数导入map中,完成对list中元素的处理。例如:
>>> map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])
[’1’, ’2’, ’3’, ’4’, ’5’, ’6’, ’7’, ’8’, ’9’]
reduce
map是将函数应用于list中的每个元素,从而得到一个新的list,而reduce则是将list中的元素利用函数累计运算类似于复合函数。
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
我们来举一个例子,比如我们自己定义一个求和函数。
>>> def add(x, y):... return x + y
...>>> reduce(add, [1,2,3])6
通过使用reduce我们可以使单个函数的功能大大加强。
比如一个二进制转十进制转换器(顺便复习一下):
a=[]def f(x):
for i in x:
a.append(int(i)) #上面的程序把数字字符串转化为整数的list
def g(x,y): #在这个地方我们可以再定义一个函数
return x*2+y
return reduce(g,a) >>> f(’536’)32
(自己编的程序比较简陋。。)大家可以看到reduce的应用。并发现Python函数定义的灵活性。
filter
Python内建的filter()函数用于过滤序列。
和map()类似,filter()也接收一个函数和一个序列。和map()不同的时,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。
例如,在一个list中,删掉偶数,只保留奇数,可以这么写:
def is_odd(n):
return n % 2 == 1
filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])# 结果: [1, 5, 9, 15]
思考题:请尝试用filter()删除1~100的素数。(以后会有更好的方法)
sorted
排序原理:
排序也是在程序中经常用到的算法。排序的核心是比较两个元素的大小。如果是数字,我们可以直接比较,但如果是字符串或者两个dict呢?直接比较数学上的大小是没有意义的,因此,比较的过程必须通过函数抽象出来。通常规定,对于两个元素x和y,如果认为x < y,则返回-1,如果认为x == y,则返回0,如果认为x > y,则返回1,这样,排序算法就不用关心具体的比较过程,而是根据比较结果直接排序。
>>> sorted([36, 5, 12, 9, 21])[5, 9, 12, 21, 36]
同样的sorted()也是一个高阶函数。我们可以通过上述排序原理利用自己定义的函数来对一个序列进行排序。比如倒序:
def daoxu(x, y):
if x > y:
return -1
if x < y:
return 1
return 0
我们利用这个函数相当于改变了排序的规则(负负得正啊,是不是)
传入自定义的比较函数daoxu,就可以实现倒序排序:
>>> sorted([36, 5, 12, 9, 21], daoxu)[36, 21, 12, 9, 5]
默认情况下,对字符串排序,是按照ASCII的大小比较的,由于’Z’ < ’a’,结果,大写字母Z会排在小写字母a的前面。现在,我们提出排序应该忽略大小写,按照字母序排序。要实现这个算法,不必对现有代码大加改动,只要我们能定义出忽略大小写的比较算法就可以:
这是我们的想法就是定义一个函数先把一个list中的字符串全变成小写,然后再比较顺序,这样就可以忽略大小写的影响了。
def ignore(s1, s2):
u1 = s1.upper()
u2 = s2.upper()
if u1 < u2:
return -1
if u1 > u2:
return 1
return 0
现在把这个函数扔到sorted()中来实现我们想要的排序
>>> sorted([’bob’, ’about’, ’Zoo’, ’Credit’], ignore)
[’about’, ’bob’, ’Credit’, ’Zoo’]
好了以上我们就介绍了四种高阶函数。从上述例子可以看出,高阶函数的抽象能力是非常强大的,而且,核心代码可以保持得非常简洁。
小结:
这篇文章讲述的主要是对list进行处理的函数。函数的应用需要经常的练习,并在练习中发现问题,(比如缩进,return的位置都会影响最终结果),有时更需要扎实的数学功底比如上文中素数的提取方法(更好的算法更高效)。
文章来源:China’s Prices Project
标签: