作者:jofranks 原创作品,转载请标明出处!版权所有,侵权必究!
来源:http://blog.csdn.net/jofranks
函数: 是对程序逻辑进行结构化或过程化的一种编程方法!
来看一下函数的形式:
>>> def bar():
return ('abc', [2, 's'], 'ss')
>>> x, y, z = bar()
>>> (a, b, c) = bar()
>>> s = bar()
>>> s
('abc', [2, 's'], 'ss')
>>> x
'abc'
>>> a
'abc'
>>> b
[2, 's']
>>>
OK,看一下一个小游戏代码,熟悉一下python的函数调用和上一节的异常处理:
from operator import add, sub
from random import randint, choice
ops = {'+': add, '-': sub}
MAXTRIES = 2
def doprob():
op = choice('+-')#随机选择操作符
nums = [randint(1, 10) for i in range(2)]#或者[randint(1, 10), randint(1, 10)]
nums.sort(reverse = True)#由大到小排序
ans = ops[op](*nums)
pr = '%d %s %d=' % (nums[0], op, nums[1])
oops = 0
while True:
try:
if int(raw_input(pr)) == ans:
print 'correct'
break
if oops == MAXTRIES:
print 'answer\n%s%d'%(pr, ans)
else:
print 'invorrect... try again'
oops += 1
except (KeyboardInterrupt, EOFError, ValueError):
print 'invalid input... try again'
def main():
while True:
doprob()
try:
opt = raw_input('Again? [y]').lower()
if opt and opt[0] == 'n':
break
except (KeyboardInterrupt, EOFError):
break
if __name__ == '__main__':
main()
跟其他语言相同,python中你也可以再不同的函数中使用相通的变量,然后可以在另一个函数中一同调用!
内嵌/内部函数
如:
你调用foo()是正确的,调用bar()就会报错,因为他是在foo函数中定义的。>>> def foo(): def bar(): print 'bar' print 'foo' bar() >>> foo() foo bar >>> bar() Traceback (most recent call last): File "<pyshell#8>", line 1, in <module> bar() NameError: name 'bar' is not defined
可变长的函数参数
有时候我们要使用可变长的函数参数,变长的函数在函数声明中不是显示命名的,因为参数的数目在运行时之前是未知的。
函数的调用提供了两种类型:关键字,非关键字两种参数类型,python用两种方法来支持变长的参数。
在C 中我们有varargs!(va_list, va_start,va_end), 在我们的python中也类似!
关键字变量参数带元组的函数语法:
星号操作符之后的形参将作为元组传递给参数。def fun([formal_args,] *vargs_tuple):
>>> def t(arg1, arg2 = 't', *the): print 'formal arg1:', arg1 print 'formal arg2:', arg2 >>> def t(arg1, arg2 = 't', *the): print 'formal arg1:', arg1 print 'formal arg2:', arg2 for eachX in the: print 'another arg:', eachX >>> t('s') formal arg1: s formal arg2: t >>> t(23, 44) formal arg1: 23 formal arg2: 44 >>> t(22, 33, 44, 55, 66, 77, 88) formal arg1: 22 formal arg2: 33 another arg: 44 another arg: 55 another arg: 66 another arg: 77 another arg: 88
非关键字变量参数字典 参数函数的的定义:
def fun([formal_args,][*vargst,] **vargsd): ...
在这里,**为了不和幂运算发生混淆,重载了! 关键字变量参数应该是函数定义的最后一个参数,带**!下面看字典的例子:
>>> def t(arg1, arg2 = 't', **the): print 'formal arg1:', arg1 print 'formal arg2:', arg2 for eachX in the.keys(): print 'Xtra arg %s: %s' % (eachX, str(the[eachX])) >>> t(12, 23, c='s') formal arg1: 12 formal arg2: 23 Xtra arg c: s >>> t('e', 's', men=('as', 'df')) formal arg1: e formal arg2: s Xtra arg men: ('as', 'df')
要注意的是: 关键字字典参数必须出现在非关键字元组之后!如:
>>> def t(arg1, arg2 = 't', *ts, **the): print 'formal arg1:', arg1 print 'formal arg2:', arg2 for s in ts: print 'additional non-keyword arg:', s for sp in the.keys(): print "additional keyword arg '%s': %s" % (sp, the[sp]) >>> t(33, 4324, 'sdf', f = 324, ss = 333) formal arg1: 33 formal arg2: 4324 additional non-keyword arg: sdf additional keyword arg 'ss': 333 additional keyword arg 'f': 324
当然我们还可以这样来调用函数:
>>> t(22, 33, *(3, 4), **{'s':2, 'd':4}) formal arg1: 22 formal arg2: 33 additional non-keyword arg: 3 additional non-keyword arg: 4 additional keyword arg 's': 2 additional keyword arg 'd': 4 >>> a = (3, 4, 5) >>> b = {'a':1, 'b':2} >>> t(33, 44, *a, **b) formal arg1: 33 formal arg2: 44 additional non-keyword arg: 3 additional non-keyword arg: 4 additional non-keyword arg: 5 additional keyword arg 'a': 1 additional keyword arg 'b': 2
函数式编程
匿名函数:
内建函数:apple() filter() map() reduce()lambda [arg1[, arg2,...argn]]:expression
来看一下实例:>>> def true(): return True >>> true() True >>> trues = lambda: True >>> trues() True
OK!看一下带参数的函数:
>>> def add(x, y): return x+y >>> add(1, 2) 3 >>> adds = lambda x, y: x+y >>> adds(1, 2) 3
lambda是一个函数的单行版本,但是他不同于C++中的inline函数,这种语句的目的是由于性能的原因,在调用时绕过函数的栈分配!
1、apple()
python1.6已经摒弃。
2、filter()
过滤器!将好的过滤出来!filter函数将给定的序列的每个元素调用给定的布尔函数,每个返回true的元素添加到列表中!
用图来解释:
OK 。我们来看一下列子:
>>> from random import randint >>> def s(n): return n%3 >>> allNums = [] >>> for eachNum in range(10): allNums.append(randint(1, 99)) >>> print filter(s, allNums) [28, 46, 52, 8, 26, 61, 67, 53, 62]
还记得刚才看到的lambda吧!我么可以把s函数用lambda代替: lambda n: n%3或者是print改写成:
print [n for n in allNums if n%3]
当然,s函数是不能要的!
其实我们用列表解析会更加灵活!我们用r代替randint
看是不是更加的简单了啊!!!>>> from random import randint as r >>> print [n for n in [r(1, 99) for i in range(10)] if n % 3]
3、map()
map与filter相似!而map是映射!他返回一个含有所有返回值的列表!
比较一下:
来看一下图列:>>> filter((lambda x: x+2),[0, 1, 2,]) [0, 1, 2] >>> map((lambda x: x+2), [0, 1, 2]) [2, 3, 4]
然后多个序列作用到map上呢?
>>> map((lambda x: x+2), [0, 1, 2]) [2, 3, 4] >>> map(lambda x, y: x + y, [1, 2, 3,], [1, 2, 3]) [2, 4, 6] >>> map(lambda x, y:(x+y, x-y), [1, 2, 3], [1, 2, 3]) [(2, 0), (4, 0), (6, 0)]
然而我们还有一个函数式zip,他的功能是什么呢?
>>> map(None, [1, 2, 3], [1, 2, 3]) [(1, 1), (2, 2), (3, 3)] >>> zip([1, 2, 3], [1, 2, 3]) [(1, 1), (2, 2), (3, 3)]
Ok,我们看了代码,应该会明白了吧!!!
4、reduce()
偏函数:reduce(f, [1, 2, 3])
等价于f(f(1, 2), 3)
用图来解释就是:
>>> reduce(lambda x,y:x+y, range(10)) 45 >>> reduce(lambda x,y:x+y, 'hello world') 'hello world'
先来看一段代码:
>>> from operator import add, mul >>> from functools import partial >>> add1 = partial(add, 1) >>> mul100 = partial(mul, 100) >>> add1(10) 11 >>> mul100(10) 1000
通过代码可以看出,利用partial,你可以实现泛华。。 也就是add两个参数中先给你提供一个,然后成立新的函数,提供给这个新函数一个参数就可以了!当调用含有多个参数的函数的时候,这是一种很好的方法! 这就是PFA(PARTIAL FUNCTION APPLICATION)偏函数应用!
再来看一个实用点的函数:
大家应该能看懂吧,16进制转换成int十进制! 当然你也可以修改base>>> a = partial(int, base = 16) >>> a('fff') 4095 >>> a('000f') 15 >>> a('0010')
生成器:
一个函数或者子程序只返回一次,但是一个生成器能暂停执行并返回一个中间结果! 这就是生成器一个带yield语句的函数!
>>> def s(): yield 1 yield 2 yield 3 >>> for eachItem in s(): print eachItem 1 2 3 >>> m = s() >>> m.next() 1 >>> m.next() 2 >>> m.next() 3 >>> m.next() Traceback (most recent call last): File "<pyshell#209>", line 1, in <module> m.next() StopIteration
通过上面的代码大家会看清楚吧!如果你想结束生成器那就用close()方法
--------------2012/7/30
---------------jofranks 于南昌