11.1 什么是函数?

函数式对程序逻辑进行结构化或过程化的一种编程方法,能够整块代码巧妙地隔离成易于管理的小块

以下为创建,使用,或引用函数的方法:

declaration/definition def foo(): print 'bar'

function object/reference foo

function call/invocation foo()

11.1.1 函数 vs 过程

11.1.2 返回值与函数类型

函数会向调用者返回一个值

下面hello() 函数的行为就像一个过程,没有返回值,如果保存了返回值,该值为None

>>> def hello():

...    print 'hello world'

...

>>> res = hello()

hello world

>>> hello()

hello world

>>> res

>>> print res

None

>>> type(res)

<type 'NoneType'>

>>> type(hello())

hello world

<type 'NoneType'>

python 里的函数可以返回一个值或者对象

>>> def foo():

...    return ['xyz', 100000, -98.6]

...

>>> def bar():

...    return 'abc', [42,'python'], "Guido"

...

>>> foo()

['xyz', 100000, -98.6]

>>> bar()

('abc', [42, 'python'], 'Guido')

foo函数返回一个列表,bar()函数返回一个元祖,由于元祖语法上不需要一定带上圆括号,所以让人真的以为可以i返回多个对象,如果我们要恰当地给这个元祖加上括号,bar()的定义看起来会是这样:

>>> def bar():

...    return ('abc', [42, 'python'], 'Guido')

...

>>> bar()

('abc', [42, 'python'], 'Guido')

从返回值角度考虑,可以通过很多方式来存储元祖:

>>> aTuple = bar()

>>> x, y, z = bar()

>>> (a, b, c) = bar()

>>>

>>> aTuple

('abc', [42, 'python'], 'Guido')

>>> x, y, z

('abc', [42, 'python'], 'Guido')

>>> (a, b, c)

('abc', [42, 'python'], 'Guido')

11.2  调用函数

11.2.1 函数操作符

11.2.2 关键字参数

通过函数调用中的参数名字来区分参数,这样规范允许参数缺货死或不按顺序,因为解释器能通过给出的关键字来匹配参数的值:

例:

def foo(x):

foo_suite # presumably does some processing with 'x'

标准调用 foo() foo(42) foo('bar') foo(y)

关键字调用 foo() foo(x=42) foo(x='bar') foo(x=y)

例,假设一个函数叫net_conn(),需要两个参数host和port:

def net_conn(host,port):

net_conn_suite

只要按照函数声明中参数定义的顺序输入恰当的参数,自然就可以调用这个函数

net_conn('kappa',8080)

host参数得到字符串'kappa',port参数得到整数8080,也可以不按顺序输入,但要输入相应的参数名:

net_conn(port=8080,host='chino')

当参数缺失,可以使用默认参数

11.2.3 默认参数:

默认参数就是声明了默认值的参数

11.2.4 参数组:

Python同样允许执行一个没有显式定义参数的函数,相应的方法是通过一个把元祖(非关键字参数)或字典(关键字参数)作为参数组传递给函数

func(*tuple_grp_nonkw_args,**dict_grp_kw_args)

tuple_grp_nonkw_args是以元祖形式体现的非关键字参数组

dict_grp_kw_args是装有关键字参数的字典

你也可以给出形参! 这些参数包括标准的位置参数和关键字参数

func(positonal_args,keyword_args,*tuple_grp_nonkw_args,**dict_grp_kw_args)

例:随机选择数字及一个算术函数,显示问题,以及验证结果,在3次错误尝试以后给出结果,等到用户输入一个正确的答案后便会继续运行:

# vi easyMath.py

----------------------------

#!/usr/bin/env 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)]

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 '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(KeyboadInterrupt,EOFError):

break

if __name__ == '__main__':

main()

----------------------------

注:

ans = ops[op](*nums)

ops = {'+':add,'-':sub} 是个字典

op则等于+或者-,   假设op是'+'则ops[op] 则取出add这个函数

而后面的(*nums)则相当于将nums中的元素依次作为参数传递给add这个函数比如nums = [3,4]

则ops[op](*nums) 相当于 add(3,4)

至于这样的调用函数的形式你可以去看下python2.x的内置函数apply这里的ops[op]相当于apply的functions函数*nums相当于apply的args函数

11.3 创建函数

11.3.1 def语句

函数是用def语句来创建的,语法如下:

def function_name(arguments):

"function_documentation_string"

function_body_suite

>>> def helloSomeone(who):

...     'returns a salutory string customized with the input'

...     return "Hello " + str(who)

...

>>> helloSomeone('haha')

'Hello haha'

11.3.2 声明与定义比较

11.3.3 前向引用

Python不允许在函数未声明之前,对其进行引用或者调用

>>> def foo():

...     print 'in foo()'

...     bar()

如果我们调用函数foo(),肯定会失败,因为函数bar()未声明:

>>> foo()

in foo()

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

File "<stdin>", line 3, in foo

NameError: global name 'bar' is not defined

现在定义函数bar(),在函数foo()前给出bar()声明:

>>> def bar():

...    print 'in bar()'

...

>>> def foo():

...    print 'in foo()'

...    bar()

...

现在可以安全调用foo()

>>> foo()

in foo()

in bar()

我们可以在函数bar()前定义函数foo()

>>> def foo():

...    print 'in foo()'

...    bar()

...

>>> def bar():

...    print 'in bar()'

仍旧非常好的运行,不会有前向引用问题

因为我们声明foo(),然后再声明bar(),接着调用foo(),但那时,bar()已经存在,所以调用成功

>>> foo()

in foo()

in bar()

11.3.4 函数属性

import foo, bar

print foo.x + bar.x

>>> def foo():

...    'foo() -- properly created doc string'

...

>>> def bar():

...     pass

...

>>> bar.__doc__ = '0ops, forgot the doc str above'

>>> bar.version = 0.1

>>> help(foo)

Help on function foo in module __main__:

foo()

foo() -- properly created doc string

>>> print bar.version

0.1

>>> print foo.__doc__

foo() -- properly created doc string

>>> print bar.__doc__

0ops, forgot the doc str above

11.3.5 内部/内嵌函数

在函数体内创建另一个函数是完全合法的,这种函数叫做内部/内嵌函数

创建内部函数的方法是在外部函数的定义体内定义函数(用def关键字)

>>> def foo():

...   def bar():

...     print 'bar() called'

...     print 'foo() called'

...   bar()

...

>>> foo()

bar() called

foo() called

>>> bar()

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

NameError: name 'bar' is not defined

内部函数在于整个函数体都在外部函数的作用于之内,如果没有任何对bar()的外部引用,那么除了函数体内,任何地方都不能对其进行调用,上述代码异常的原因就是如此

11.3.6 函数(与方法)装饰器

装饰器的语法以@开头,接着是装饰器的名字和可选册数

下面是被修饰的函数,和装饰函数的可选参数:

@decorator(dec_opt_args)

def func2Bdecorated(func_opt_args):

例:

class MyClass(object):

@staticmethod

def statciFoo():

..

@deco2

@deco1

def func(arg1,arg2,...):pass

这和创建一个组合函数是等价的

函数组合用数学来定义就像这样: (g * f)(x) =g(f(x)) 对于在python中的一

致性

@g

@f

def foo():

...

什么时候使用带参数的装饰器:

无参数装饰器:

@deco

def foo(): pass

....非常直接

foo = deco(foo)

有参数装饰器:

@decomaker(deco_args)

def foo(): pass

...

foo =decomaker(deco_args)(foo)

@deco1(deco_arg)

@deco2

def func():pass

This is equivalent to: 这等价于

func = deco1(deco_arg)(deco2(func))

装饰器实际就是函数,我们在运行函数之前可以运行一些预备代码,之后做一些清理工作

1.可以引入日志

2.增加计时逻辑来检测性能

3.给函数加入事务能力

例:

-------------------------------

#!/usr/bin/env python

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()

-------------------------------

# python decp.py

[Wed Oct 23 03:10:58 2013] foo() called

[Wed Oct 23 03:11:03 2013] foo() called

[Wed Oct 23 03:11:04 2013] foo() called

11.4 传递函数:

所有对象都是通过引用来传递的,函数也不例外:

>>> def foo():

...    print 'in foo()'

...

>>> bar = foo

>>> bar()

in foo()

当我们把foo赋值给bar时,bar和foo引用了同一个函数对象,所以能以和调用foo()相同的方式来调用bar().

我们甚至可以把函数作为参数传入其他函数来进行调用

>>> def bar(argfunc):

...    argfunc()

...

>>> bar(foo)

in foo()

例:传递和调用(内建)函数:

# vi numConv.py

--------------------------

#!/usr/bin/env python

def convert(func,seq):

'conv. sequence of numbers to same type'

return [func(eachNum) for eachNum in seq]

myseq = (123,45.67, -6.2e8, 9999999999L)

print convert(int, myseq)

print convert(long, myseq)

print convert(float,myseq)

--------------------------

# python numConv.py

[123, 45, -620000000, 9999999999L]

[123L, 45L, -620000000L, 9999999999L]

[123.0, 45.67, -620000000.0, 9999999999.0]

11.5 形式参数:

python函数的形参集合由在调用时要传入参数的所有参数组成

11.6 位置参数:

这些都是我们熟悉的标准化参数.

>>> def foo(who):

...   print "Hello", who

...

>>> foo()

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

TypeError: foo() takes exactly 1 argument (0 given)

>>> foo('World!')

Hello World!

>>> foo('Mr', 'World!')

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

TypeError: foo() takes exactly 1 argument (2 given)

foo()函数有一个位置参数,那意味着任何对foo()的调用必须有唯一的一个参数

否则会报TypeError异常

11.5.2 默认参数

对于默认参数如果在函数调用时没有为参数提供值则使用预先定义的默认值

python中用默认值生命变量的语法是所有的位置参数必须出现在任何一个默认参数之前

def func(posargs, defarg1=dvall, defarg2=dval2,...):

'function_documentation_string'

function_body_suite

每个默认参数都紧跟一个用默认值的赋值语句,如果在函数调用时木有给出值,那么这个赋值就会实现.

>>> def taxMe(cost, rate=0.0825):

...     return cost + (cost * rate)

...

>>> taxMe(100)

108.25

>>> taxMe(100,0.05)

105.0

如果没有按正确的顺序给出参数,就会产生一个语法错误:

>>> def taxMe2(rate=0.0825, cost):

...     return cost * (1.0 + rate)

...

File "<stdin>", line 1

SyntaxError: non-default argument follows default argument

让我们再看下关键字参数:

def net_conn(host,port):

net_conn_suite

如果命名了参数,这里可以不按顺序给出参数

net_conn('kappa',8000)

net_conn(port=8080,host='chino')

如果我们将默认参数引入这个模式

def net_conn(host,port=80,stype='tcp'):

net_conn_suite

未使用默认参数:

net_conn('phaze', 8000,'udp')

使用默认参数:

net_conn('kappa')

net_conn('chino', stype='icmp')

net_conn(stype='udp',host='solo')

net_conn('deli',8080)

net_conn(port=81, host='chino')

例:

--------------------------

#!/usr/bin/env python

from urllib import urlretrieve

def firstNonBlank(lines):

for eachLine in lines:

if not eachLine.strip():

continue

else:

return eachLine

def firstLast(webpage):

f = open(webpage)

lines = f.readlines()

f.close()

print firstNonBlank(lines),

lines.reverse()

print firstNonBlank(lines),

def download(url='http://www.baidu.com',process=firstLast):

try:

retval = urlretrieve(url)[0]

except IOError:

retval = None

if retval:

process(retval)

if __name__ == '__main__':

download()

--------------------------

11.6 可变长度的参数:

11.6.1 非关键字可变长参数(元组)

def function_name([formal_args] *vargs_tuple):

'function_documentation_string'

function_body_suite

例:

>>> def tupleVarArgs(arg1, arg2='default8', *theRest):

...      'display regular args and non-keyword variable args'

...      print 'formal arg 1:', arg1

...      print 'formal arg 2:', arg2

...      for eachXtrArg in theRest:

...         print 'another arg:' , eachXtrArg

...

>>> tupleVarArgs('abc')

formal arg 1: abc

formal arg 2: default8

>>> tupleVarArgs(23,4.56)

formal arg 1: 23

formal arg 2: 4.56

>>> tupleVarArgs('abc',123,'xyz',456.789)

formal arg 1: abc

formal arg 2: 123

another arg: xyz

another arg: 456.789

11.6.2 关键字变量参数(Dictionary)

def function([formal_args,][*vargst,] **vargsd):

function_documentation_string function_body_suite

最后一个的参数是使用了**的关键字变量参数

例:

>>> def dictVarArgs(arg1, arg2='default8', **theRest):

...     'display 2 regular args and keyword variable args'

...     print 'formal arg1:', arg1

...     print 'formal arg2:', arg2

...     for eachXtrArg in theRest.keys():

...        print 'Xtra arg %s: %s' %(eachXtrArg, str(theRest[eachXtrArg]))

输出:

>>> dictVarArgs(1220,740.0,c='grail')

formal arg1: 1220

formal arg2: 740.0

Xtra arg c: grail

>>> dictVarArgs(arg2='tales', c=123, d='poe',arg1='mystery')

formal arg1: mystery

formal arg2: tales

Xtra arg c: 123

Xtra arg d: poe

>>> dictVarArgs('one',d=10,e='zoo',men=('freud','gaudi'))

formal arg1: one

formal arg2: default8

Xtra arg men: ('freud', 'gaudi')

Xtra arg e: zoo

Xtra arg d: 10

关键字和非关键字可变长参数都有可能用在同一个函数中,只要关键字字典是最后一个参数并且非关键字元组先于它之前出现:

>>> def newfoo(arg1, arg2, *nkw, **kw):

...     'display regular 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.keys():

...       print "additional keyword arg '%s': %s" %(eachKW,kw[eachKW])

输出:

>>> newfoo('wolf',3,'projects',freud=90,gamble=96)

arg1 is: wolf

arg2 is: 3

additional non-keyword arg: projects

additional keyword arg 'gamble': 96

additional keyword arg 'freud': 90

11.6.3 调用带有可变长参数对象函数:

>>> newfoo(10, 20, 30, 40, foo=50, bar=60)

arg1 is: 10

arg2 is: 20

additional non-keyword arg: 30

additional non-keyword arg: 40

additional keyword arg 'foo': 50

additional keyword arg 'bar': 60

>>> newfoo(2, 4, *(6, 8), **{'foo': 10, 'bar': 12})

arg1 is: 2

arg2 is: 4

additional non-keyword arg: 6

additional non-keyword arg: 8

additional keyword arg 'foo': 10

additional keyword arg 'bar': 12

最终,我们将在另外进行一次调用,但是是在函数调用之外来创建我们的元组和字典.

>>> aTuple = (6,7,8)

>>> aDict = {'z':9}

>>> newfoo(1,2,3, x=4, y=5, *aTuple,**aDict)

arg1 is: 1

arg2 is: 2

additional non-keyword arg: 3

additional non-keyword arg: 6

additional non-keyword arg: 7

additional non-keyword arg: 8

additional keyword arg 'y': 5

additional keyword arg 'x': 4

additional keyword arg 'z': 9

函数式编程举例:

# vi testit.py

-----------------------------

#!/usr/bin/env python

def testit(func, *nkwargs, **kwargs):

try:

retval = func(*nkwargs, **kwargs)

result = (True,retval)

except Exception, diag:

result = (False,str(diag))

return result

def test():

funcs = (int, long, float)

vals = (1234, 12.34, '1234', '12.34')

for eachFunc in funcs:

print '-' * 20

for eachVal in vals:

retval = testit(eachFunc,eachVal)

if retval[0]:

print '%s(%s) =' %(eachFunc.__name__, 'eachVal'),retval[1]

else:

print '%s(%s) = FAILED:' %(eachFunc.__name__, 'eachVal'),retval

[1]

if __name__ == '__main__':

test()

-----------------------------

单元测试函数test()在一个为4个数字的输入集合运行了一个数字转换函数的集合,为了确定这样的功能,在测试中有两个失败的案例,这里是运行脚本的输出:

# python testit.py

--------------------

int(eachVal) = 1234

int(eachVal) = 12

int(eachVal) = 1234

int(eachVal) = FAILED: invalid literal for int() with base 10: '12.34'

--------------------

long(eachVal) = 1234

long(eachVal) = 12

long(eachVal) = 1234

long(eachVal) = FAILED: invalid literal for long() with base 10: '12.34'

--------------------

float(eachVal) = 1234.0

float(eachVal) = 12.34

float(eachVal) = 1234.0

float(eachVal) = 12.34

11.7 函数式编程

11.7.1 匿名函数与lambda

lambda [arg1[,arg2, ...argN]]:expression

def true():

return True

Python中单行函数可以和标题写在同一行

def true(): return True

利用匿名函数lambda写法实现上面函数的效果:

lambda : True

例:

>>> def true(): return True

...

>>> true()

True

>>> lambda : True

<function <lambda> at 0x8f9c374>

>>> true = lambda :True

>>> true()

True

我们可以把lambda表达式赋值给一个如列表和元组的数据结构

例:我们设计一个带两个数字或字符串参数,返回数字之和或者已拼接的字符串的函数

def add(x,y): return x + y

lambda x,y :x + y

默认以及可变参示例:

def usualllyAdd2(x,y=2): return x+y

lambda x,y=2: x+y

def showAllAsTuple(*z): return z

lambda *z : z

实例:

>>> true = lambda :True

>>> true()

True

>>> a = lambda x,y=2: x + y

>>> a(3)

5

>>> a(3,5)

8

>>> a(0,9)

9

>>> b= lambda *z: z

>>> b(23,'zyz')

(23, 'zyz')

>>> b(42,)

(42,)

11.7.2 内建函数 apply(),filter(),map(),reduce()

apply(func[, nkw][, kw])

用可选的参数来调用func,nkw为非关键字参数,kw为关键字参数,返回值是函数调用的返回值

filter(func,seq)

调用一个布尔函数func来迭代遍历每个seq中的元素,返回一个使func返回值为true的元素的序列

def filter(bool_func, seq):

filtered_seq = []

for eachItem in seq:

if bool_func(eachItem):

filtered_seq.append(eachItem)

return filtered_seq

例:

# vi oddnogen.py

---------------------

#!/usr/bin/env python

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)

---------------------

odd()用来对一个整数取余,如果返回0为偶数,返回1为奇数

后面阐述10个在1到100的随机数,然后调用filter(),过滤掉返回值0即为假的偶数,剩下的即为奇数.

输出:

# python oddnogen.py

[33, 73, 85, 41]

# python oddnogen.py

[45, 77, 49, 85, 35, 21]

# python oddnogen.py

[21, 93, 99]

# python oddnogen.py

[75, 59, 73, 85, 31, 31, 33, 37, 29]

第一次重构,利用lambda表达式:

--------------------------------

#!/usr/bin/env python

from random import randint

allNums = []

for eachNum in range(9):

allNums.append(randint(1,99))

print filter(lambda n: n%2,allNums)

--------------------------------

# python oddnogen1.py

[7, 73, 39, 77, 61, 9, 61]

# python oddnogen1.py

[31, 57, 63, 23, 3, 65]

重构2,利用list迭代解析

----------------------------

#!/usr/bin/env python

from random import randint

allNums = []

for eachNum in range(9):

allNums.append(randint(1,99))

print [n for n in allNums if n%2]

----------------------------

# python oddnogen2.py

[59, 57, 59, 75, 37]

# python oddnogen2.py

[99, 89, 49, 71, 45, 3]

重构3: 列表解析简化

-------------------------

#!/usr/bin/env python

from random import randint as ri

print [n for n in [ri(1,99) for i in range(9)] if n%2]

-------------------------

# python oddnogen3.py

[11, 7, 35, 71, 87]

# python oddnogen3.py

[83, 61, 17, 13, 21, 55]

map(func,seq1[,seq2...])

将函数func作用于给定序列的每个元素,并用一个列表来提供返回值,如果func为None,func表现为一个身份函数,返回一个含有每个序列中元素集合的N个元组列表

def map(func,seq):

mapped_seq=[]

for eachItem in seq:

mapped_seq.append(func(eachItem))

return mapped_seq

例:

>>> 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()例子:

>>> 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(func,seq[, init])

将二元函数作用于seq序列的元素,每次携带一对,连续的将现有的结果和下雨给值作用在获得的随后结果上,最后减少我们的序列为一个单一返回值,如果初始值init给定,第一个比较会是init和第一个序列元素而不是序列的头两个元素

reduce(func,[1,2,3]) = func(func(1,2),3)

if init is None:

res = lseq.pop(0)

else:

res = init

for item in lseq:

res = bin_func(res, item)

return res

例:

>>> def mySun(x,y): return x+y

...

>>> lambda x,y: x+y

<function <lambda> at 0x89c9374>

---------------------------------

>>> def mySum(x,y): return x+y

...

>>> allNums = range(5)

>>> total = 0

>>> for eachNum in allNums:

...     total = mySum(total,eachNum)

...

>>> print 'the total is:', total

the total is: 10

-----------------------------------

简化:

>>> print 'the total is:',reduce((lambda x,y: x+y),range(5))

the total is: 10

给出了上面的输入,reduce()函数运行了如下算数操作:

((((0 + 1) + 2) + 3) + 4) => 10

注:用 list 的头两个元素(0,1),调用mySum()来得到1,然后用现在的结果和下一个元素2来再次调用mySum(),再用这次调用中获得结果,与下面的元素3配对然后调用mySum(),最终拿整个前面的求和和4来调用mySum()得到10,10即为最终返回值

11.7.3 偏函数应用:

简单的函数式例子:

>>> 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)

>>> add1(10)

11

>>> add1(1)

2

>>> mul100(10)

1000

>>> mul100(500)

50000

将二进制(作为字符串) 转化为整数:

>>> int('10010',2)

18

>>> baseTwo = partial(int,base=2)

>>> baseTwo.__doc__ = 'Convert base 2 string to an int.'

>>> baseTwo('10010')

18

这个例子使用了int()内建函数并将base固定为2来制定二进制字符串转化

警惕关键字:

如果你创建了不带base关键字的偏函数,会让参数以错误的顺序传入int(),因为固定参数的总是放在运行时参数的左边

比如: baseTwoBAD(x) = int(2,x)

2会作为需要转化的数字,base作为'10010'来传入,从而产生一个异常:

>>> baseTwoBAD = partial(int,2)

>>> baseTwoBAD('10010')

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

TypeError: an integer is required

# vi ppfaGUI.py

----------------------------

#!/usr/bin/env python

from functools import partial

import Tkinter

root = Tkinter.Tk()

MyButton = partial(Tkinter.Button, root, fg='white',bg='blue' )

b1 = MyButton(text='Button 1')

b2 = MyButton(text='Button 2')

qb = MyButton(text='QUIT', bg='red', command=root.quit)

b1.pack()

b2.pack()

qb.pack(fill=Tkinter.X, expand=True)

root.title('PFAs!')

root.mainloop()

----------------------------

11.8 变量作用域

11.8.1 全局变量与局部变量:

global_str = 'foo'

def foo():

local_str = 'bar'

return global_str + local_str

global_str是全局变量,而local_str是局部变量,foo()函数可以对全局和局部变量进行访问,而代码主体部分只能访问全局变量

11.8.2 globa语句:

如果将全局变量的名字声明在一个函数体内,全局变量的名字能被局部变量给覆

盖掉

defoo():

print "\ncallingfoo"

bar =200

print "in foo(),bar is",bar

bar =100

print "in_main_,bar is",bar foo()

print "\nin__main__,bar is (still), bar

例子:

>>> is_this_global = 'xyz'

>>> def foo():

...     global is_this_global

...     this_is_local = 'abc'

...     is_this_global = 'def'

...     print this_is_local + is_this_global

...

>>> foo()

abcdef

>>> print is_this_global

def

11.8.3 作用域的数字

>>> def foo():

...    m = 3

...    def bar():

...       n = 4

...       print m + n

...    print m

...    bar()

...

>>> foo()

3

7

11.8.4 闭包

闭包将内部函数自己的代码和作用于以及外部函数的作用结合起来,闭包的词法变量不属于全局名字空间域或者局部的一而属于其他的名字空间

>>> def counter(start_at=0):

...     count = [start_at]

...     def incr():

...         count[0] += 1

...         return count[0]

...     return incr

...

>>> count = counter(5)

>>> print count()

6

>>> print count()

7

>>> count2 = counter(100)

>>> print count2()

101

>>> print count()

8

>>> print count2()

102

11.8.5 作用域和lambda

python的lambda匿名函数遵循和变准函数一样的作用域规则,一个lambda表达式定义了新的作用域,就像函数定义,所以这个作用域除了局部lambda函数,对于程序其他部分,该作用域都是不能对进行访问的

>>> x = 10

>>> def foo():

...     y = 5

...     bar = lambda : x + y

...     print bar()

...

>>> foo()

15

11.8.6 变量作用域和名字空间

任何时候,总有一个或两个活动的作用域,我们要么只能访问全局作用域的模块的最高级,要么在一个我们能访问局部作用域和全局作用域的函数体内执行

例: 局部变量隐藏了全局变量(有问题)

# vi scope.py

-------------------------------

#!/usr/bin/env python

j, k = 1, 2

def procl():

j, k = 3, 4

print "j == %d and k == $d" % (j,k)

k = 5

def proc2():

j = 6

procl()

print "j == %d and k == %d" % (j,k)

j = 7

procl()

print "j == %d and k == %d" % (j,k)

j = 8

procl2()

print "j == %d and k == %d" % (j,k)

-------------------------------

11.9 *递归

如果函数包含了对其自身的调用,该函数就是递归的

def factorial(n):

if n ==0 or n==1:

return 1

else:

return (n*factorial(n-1))

11.10 生成器

11.10.1 简单的生成器特性:

当到达一个真正的返回或者函数结束没有更多值返回,一个StopIteration异常就会抛出

>>> def simpleGen():

...     yield 1

...     yield '2 --> punch!'

...

>>> myG = simpleGen()

>>> myG.next()

1

>>> myG.next()

'2 --> punch!'

>>> myG.next()

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

StopIteration

使用for循环穿过一个生成器:

>>> for eachItem in simpleGen():

...     print eachItem

...

1

2 --> punch!

创建一个带序列并从那个序列中返回一个随机元素的随机迭代器:(有问题)

>>> from random import randint

>>> def randGen(aList):

...     while len(aList) > 0:

...         yield aList.pop(randint(0,len(aList)))

...

>>> for item in randGen(['rock', 'paper', 'scissors']):

...     print item

...

rock

11.10.2 加强的生成器特性:

>>> def counter(start_at=0):

...     count = start_at

...     while True:

...         val = (yield count)

...         if val is not None:

...             count = val

...         else:

...             count +=1

...

生成器带有一个初始化的值,对每次对生成器[next()]调用以1累加计数,用户已可以选择重置这个值,如果他们非常想要用新的值来调用send()不是调用next(),这个生成器是永远运行的,所以终结他,调用close()方法

>>> count = counter(5)

>>> count.next()

5

>>> count.next()

6

>>> count.send(9)

9

>>> count.next()

10

>>> count.close()

>>> count.next()

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

StopIteration

转载于:https://blog.51cto.com/showerlee/1335949

[PYTHON] 核心编程笔记(11.Python函数和函数式编程)相关推荐

  1. 《Python核心编程》第11章 函数和函数式编程 练习

    11-3 函数. 在这个练习中,我们将实现max()和min()内建函数. (a) 写分别带两个元素返回一个较大和较小元素,简单的max2()核min2()函数.他们应该可以用任意的python 对象 ...

  2. python采用函数式编程模式吗_Python函数与函数式编程

    1 函数 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print().但你也可以自己创 ...

  3. 闭关之 C++ 函数式编程笔记(一):函数式编程与函数对象

    目录 前言 第一章 函数式编程简介 1.1 命令式与声明式编程比较 1.2 纯函数(Pure functions) 1.2.1 避免可变状态 1.3 以函数方式思考问题 1.4 函数式编程的优点 1. ...

  4. Python学习笔记11:函数修饰符

    Python学习笔记11:函数修饰符 Python有很多有趣的特性,其中函数修饰符就是一个. 我们在之前的那个web应用示例中用过如下写法: @web.route('/log') @符号后边的,就是一 ...

  5. 8.Python基础学习笔记day8-正则表达式、网络编程、进程与线程

    8.Python基础学习笔记day8-正则表达式.网络编程.进程与线程 一.正则表达式 ''' 1. [1,2,3,4]中任意取3个元素排列: A43 = 4x3x2 = 24itertools.pe ...

  6. python函数和函数式编程

    --以下所有内容均来自于蓝鲸运维SaaS开发实战公开课的ppt,我对其进行了整理做了笔记,便于以后查看学习. 函数 声明函数: def hello():print("hello functi ...

  7. python采用函数式_python -- 函数以及函数式编程

    函数以及函数式编程 到目前为止,我们的Python 代码已经实现了小的分块.它们都适合处理微小任务, 但是我们想复用这些代码,所以需要把大型代码织成可管理的代码段.代码复用的第一步是 使用函数,它是命 ...

  8. 跟着ALEX 学python day3集合 文件操作 函数和函数式编程

    声明 : 文档内容学习于 http://www.cnblogs.com/xiaozhiqi/  一. 集合 集合是一个无序的,不重复的数据组合,主要作用如下 1.去重 把一个列表变成集合 ,就自动去重 ...

  9. Python 网络爬虫笔记11 -- Scrapy 实战

    Python 网络爬虫笔记11 – Scrapy 实战 Python 网络爬虫系列笔记是笔者在学习嵩天老师的<Python网络爬虫与信息提取>课程及笔者实践网络爬虫的笔记. 课程链接:Py ...

  10. Python中的匿名函数和函数式编程

    Python中的匿名函数和函数式编程 文章目录 Python中的匿名函数和函数式编程 一.匿名函数 匿名函数的格式: 二.函数式编程 map() filter() reduce() 区别 三.'三目运 ...

最新文章

  1. Android开发实现QQ三方登录 标签: android开发qq三方登录
  2. 很幽默的讲解六种Socket IO模型
  3. VTK:图片之StaticImage
  4. java获取excle表格对象_Java使用excel工具类导出对象功能示例
  5. 【AI视野·今日Robot 机器人论文速览 第十六期】Tue, 29 Jun 2021
  6. 开源目标检测算法用于交通标志检测全方位评估
  7. 软件测试 学习之路 MYSQL安装
  8. 【Flink】Flink 实现 End to End 的 EXACTLY_ONCE
  9. python出现—with the features you requested: lxml. Do you need to install a parser library?
  10. bzoj 2843: 极地旅行社
  11. 目标检测——夏侯南溪目标检测模型之数据结构
  12. linux下用cronolog分割apache日志
  13. 从零基础入门Tensorflow2.0 ----二、4.1 wide deep 模型(函数式API)
  14. element input 自适应_input高度自适应。
  15. 2、网站重构之本地映射外网域名
  16. 我的Windows实用软件清单
  17. 【调剂】2020年中科院上海光机所接收报考硕士研究生调剂生的通知
  18. infor接口调用,okhttp不同版本使用
  19. VRAR概念的定义和要素以及技术定义和应用
  20. latex(2):公式插入

热门文章

  1. PAIP.提升效率----论项目知识库的建设。。
  2. paip.防止代码命名重复的好方法
  3. 互联网光环下的新金融群像:运营最重要的是说人话
  4. Rust : link.exe 问题 ---LNK1171 error
  5. linux ubuntu 安装 matlab 2010 及破解 详细图解
  6. 【三维路径规划】基于matlab球面矢量粒子群算法无人机三维路径规划【含Matlab源码 1682期】
  7. 【优化调度】基于matlab改进的遗传算法求解风电场优化调度问题【含Matlab源码 1245期】
  8. 【目标跟踪】基于matlab背景差分多目标捕捉【含Matlab源码 810期】
  9. 【树叶识别】基于matlab PNN神经网络树叶类别【含Matlab源码 798期】
  10. 【图像配准】基于matlab SIFT图像配准【含Matlab源码 463期】