1.
关键字参数:仅仅针对函数的调用,这种理念是让调用者通过函数调用中的参数名字来区分参数。
2.
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)];
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+'\n')) == ans:
print 'correct';
break;
if oops == MAXTRIES:
print 'answer\n%s%d'%(pr,ans)
else:
print 'incorrect...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();
参数组:可以执行一个没有显示定义参数的函数,相应的方法是通过一个元组(非关键字参数)或字典(关键字参数)作为参数数组传递给函数。
func(*tuple_grp_nonkw_args, **dict_grp_kw_args)
其中的tuple_grp_nonkw_args是以元组形式体现的非关键字参数组,dict_grp_kw_args是装有关键字参数的字典。存在这样的特性允许把变量放在元组和字典里,并在没有显示地对参数声明的情况下,调用函数。
3.
装饰器的语法以@开头,接着是装饰器函数的名字和可选的参数。紧跟着装饰器声明的是被修饰的函数,和装饰函数的可选参数。
@decorator(dec_opt_args)
def func2Bdecorated(func_opt_args):
没有参数的装饰器:
@deco
def foo():pass
foo = deco(foo)
带参数的装饰器:
@decomaker(deco_args)
def foo():pass
decomaker()用deco_args做了些事并返回函数对象,而该函数对象正是以foo作为其参数的装饰器。
foo = decokaker(deco_args)(foo);
@deco1(deco_args)
@deco2
def func(): pass
等价于:
func = deco1(deco_args)(deco2(func))
装饰器实际就是函数,他们接受函数对象。
当你看见一个装饰器函数的时候,很可能在里面找到这样的一些代码,它定义了某个函数并在定义内的某处嵌套了对目标函数的调用至少一些引用。
from time import ctime, sleep
def tsfunc(func):
def wrappedFunc():
print '[%s] %s() called' % (ctime(), func.__name__);
return func();
return wrappedFunc;
@tsfunc
def foo():
pass
foo();
sleep(4);
for i in range(2):
sleep(1);
foo();
if __name__ == '__main__':
pass
tsfunc()函数是一个显示何时调用函数的时戳的装饰器。它定义了一个内部的函数wrappedFunc(),该函数增加了时戳以及调用了目标函数。装饰器的返回值是一个"包装了"的函数。
4.
所有必须的参数都要在默认参数之前。
5.
变长的参数在函数声明中不是显式命名的。由于函数调用提供了关键字以及非关键字两种参数类型,python用这两种方法来支持变长参数。
函数调用中使用*和**符号来指定元组和字典的元素作为非关键字以及关键字参数的方法。
非关键字可变长参数(元组)
def function_name([formal_args, ] *vargs_tuple):
星号操作符之后的形参将作为元组传递给函数,元组保存了所有传递给函数的额外的参数。
只要在函数调用时给出不正确的函数参数数目,就会产生一个TypeError异常。通过末尾增加一个可变的参数列表变量,我们就能处理超出数目的参数被传入参数的情形,因为所有的额外(非关键字)参数会被添加到变量参数元组。
def tupleVarArgs(arg1, arg2='defaultB', *theRest):
'display regular args and non-keyword variable args'
print 'formal arg1:', arg1
print 'formal arg2:', arg2
for eachXtrArg in theRest:
print 'another arg:', eachXtrArg;
tupleVarArgs('abc');
tupleVarArgs(23,4.56)
tupleVarArgs('abc',123,'xyz',456.789)
在有不定数目的或者额外集合的关键字的情况中,参数被放入一个字典中,字典中的键为参数名,值为相应的参数值。
def function_name([formal_args, ][*vargst, ] **vargsd):
def dictVarArgs(arg1, arg2='defaultB', **theRest):
'display 2 regular args and keyword variable args'
print 'formal arg1:', arg1
print 'formal arg2:', arg2
for eachXtrArg in theRest:
print 'Xtra arg %s: %s' % (eachXtrArg, theRest[eachXtrArg]);
dictVarArgs(1220,740.0,c='grail');
dictVarArgs(arg2='tales', c=123, d='poe', arg1='mystery');
def newfoo(arg1, arg2, *nkw, **kw):
'display regualr args and all variable args:'
print 'arg1 is:', arg1
print 'arg2 is:', arg2
for eachNKW in nkw:
print 'additional non-keyword arg:', eachNKW;
for eachKW in kw:
print 'additional keyword arg:', eachKW;
aTuple=(6,7,8);
aDict={'z':9};
#newfoo(2,4,*(6,8), **{'foo':10, 'bar':12});
newfoo(1,2,3,x=4,y=5,*aTuple, **aDict);
6.
python用lambda关键字创建匿名函数。一个完整的lambda“语句”代表了一个表达式,这个表达式的定义体和声明放在同一行。
7.
from random import randint
def odd(n):
return n%2;
allNums = [];
for eachNum in range(9):
allNums.append(randint(1,99));
print filter(odd, allNums);
print filter(lambda n:n%2, allNums);
print [n for n in allNums if n%2];
from random import randint as ri
print [n for n in [ri(1,99) for i in range(9)] if n%2]
>>> map((lambda x:x+2), [0,1,2,3,4,5])
[2, 3, 4, 5, 6, 7]
>>> map(lambda x:x**2, range(6))
[0, 1, 4, 9, 16, 25]
>>> [x+2 for x in range(6)]
[2, 3, 4, 5, 6, 7]
>>> [x**2 for x in range(6)]
[0, 1, 4, 9, 16, 25]
>>> map(lambda x,y:x+y, [1,3,5],[2,4,6])
[3, 7, 11]
>>> map(lambda x,y:(x+y, x-y), [1,3,5], [2,4,6])
[(3, -1), (7, -1), (11, -1)]
>>> map(None, [1,3,5], [2,4,6])
[(1, 2), (3, 4), (5, 6)]
>>> zip([1,3,5], [2,4,6])
[(1, 2), (3, 4), (5, 6)]
reduce:它通过取出序列的头两个元素,将他们传入二元函数来获得一个单一的值来实现。然后又用这个值和序列的下一个元素来获得又一个值,然后继续直到整个序列的内容都遍历完毕以及最后的值会被计算出来为止。
reduce(func, [1,2,3]) = func(func(1,2),3)
我们拿了两个元素因为我们没有任何先前的值,来获得结果。这就是可选初始化初始的地方。如果给定初始化器,那么一开始的迭代会用初始化器和一个序列的元素来进行。
8.
偏函数
from operator import add, mul
from functools import partial
add1 = partial(add,1) #add1(x) == add(1,x)
mul100 = partial(mul, 100) #mul100(x) == mul(100, x)
print add1(10)
如果在一个内部函数里,对在外部作用域(但不是全局作用域)的变量进行引用,那么内部函数被认为是closure。定义在外部函数内的但由内部函数引用或者使用的变量称为自由变量。