Python核心编程读笔 10:函数和函数式编程
第11章 函数和函数式编程
一 调用函数
1 关键字参数
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) 即明确给出相应的参数名
2 参数组
Python允许程序员执行一个没有显式定义参数的函数,相应的方法是通过一个把元组(非关键字参数)或字典(关键字参数)作为参数组传递给函数。
func( *tuple_grp_nonkw_args, **dict_grp_kw_args )
3 小结
python 中允许的函数调用的完整语法为:
func( positional_args, keyword_args, *tuple_grp_nonkw_args, **dict_grp_kw_args )
二 创建函数
1 def语句
def function_name(arguments):
"function_documentation_string"
function_body_suite
特别注意:python不区分函数的声明与定义!
2 函数属性
函数也可以有用.号表示的属性
3 内部函数
在函数体内创建另外一个函数:
def foo():
def bar():
print 'bar() called'
bar() #bar()属于函数foo的内部函数,因此只能在foo函数体内部进行调用!!!
4 传递函数
python的函数和普通对象一样,可以被传递
举例:
>>> def foo():
... print 'in foo()'
...
>>> bar = foo 函数传递!
>>> bar()
in foo()
>>> def bar(argfunc):
... argfunc()
...
>>> bar(foo) 函数传递!
in foo()
三 函数参数
1 形式参数
(1)位置参数: 必须以在被调用函数中定义的准确顺序来传递
(2)默认参数
2 可变长度参数
(1)非关键字可变参数(元组)
def function_name([formal_args,] *vargs_tuple): #所有形式参数必须先于非正式的参数之前出现!!!
"function_documentation_string"
function_body_suite
举例:
def tupleVarArgs(arg1, arg2='defaultB', *theRest):
print 'formal arg 1:', arg1
print 'formal arg 2:', arg2
for eachXtrArg in theRest:
print 'another arg:', eachXtrArg
>>> tupleVarArgs('abc', 123, 'xyz', 456.789)
formal arg 1: abc
formal arg 2: 123
another arg: xyz
another arg: 456.789
(2)关键字变量参数(字典)
def function_name([formal_args,][*vargst,] **vargsd):
function_documentation_string function_body_suite
举例:
def dictVarArgs(arg1, arg2='defaultB', **theRest):
print 'formal arg1:', arg1
print 'formal arg2:', arg2
for eachXtrArg in theRest.keys():
print 'Xtra arg %s: %s' % \
(eachXtrArg, str(theRest[eachXtrArg]))
>>> dictVarArgs('one', d=10, e='zoo', men=('freud', 'gaudi'))
formal arg1: one
formal arg2: defaultB
Xtra arg men: ('freud', 'gaudi')
Xtra arg d: 10
Xtra arg e: zoo
(3)关键字和非关键字可变长参数同时出现的情形
要求:关键字字典是最后一个参数并 且非关键字元组先于它之前出现
def newfoo(arg1, arg2, *nkw, **kw):
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 'freud': 90
additional keyword arg 'gamble': 96
(4)更多举例
>>> 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 'z': 9
additional keyword arg 'x': 4
additional keyword arg 'y': 5
四 函数式编程
1 匿名函数与lambda
python 允许用 lambda 关键字创造匿名函数。匿名是因为不需要以标准的def方式来声明。
lambda [arg1[, arg2, ... argN]]: expression
举例:
def add(x, y): return x + y 等价于 lambda x, y: x + y
def usuallyAdd2(x, y=2): return x+y 等价于 lambda x, y=2: x+y
def showAllAsTuple(*z): return z 等价于 lambda *z: z
>>>a = lambda x, y=2: x + y
>>>a(3)
5
>>>b = lambda *z: z
>>> b(23, 'zyx')
(23, 'zyx')
>>> b(42)
(42,)
2 内建函数apply()、filter()、map()、reduce()
lambda 函数可以很好的和这使用了这四个函数的应用程序结合起来,因为它们都带了一个可执行的函数对象,lambda 表达式提供了迅速创造这些函数的机制
apply( func[, nkw][, kw] ) 用可选的参数来调用 func,nkw 为非关键字参数,kw 关键字参数;返回值是函数调用的返回值。
filter( func, seq) 调用一个布尔函数 func 来迭代遍历每个 seq 中的元素; 返回一个 使 func 返回值为 ture 的元素的序列。
map( func, seq1[,seq2...] ) 将函数 func 作用于给定序列(s)的每个元素,并用一个列表来提供返回值;如果 func为None,func 表现为一个身份函数,返回一个含有每个序列中元素集合的 n 个元组的列表。
reduce( func, seq[, init] ) 将二元函数作用于 seq 序列的元素,每次携带一对(先前的结果 以及下一个序列元素),连续的将现有的结果和下雨给值作用在获 得的随后的结果上,最后减少我们的序列为一个单一的返回值;如 果初始值 init 给定,第一个比较会是 init 和第一个序列元素而不 是序列的头两个元素。
举例:
filter():
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 )
改变1:用一个 lambda 表达式替换
from random import randint
allNums = []
for eachNum in range(9):
allNums.append(randint(1, 99))
print filter( lambda n: n%2, allNums ) #使用了lambda表达式!!!
改变2:list 综合使用如何能成为 filter()合适的替代者
from random import randint
allNums = []
for eachNum in range(9):
allNums.append(randint(1, 99))
print [n for n in allNums if n%2]
改变3:利用列表解析!
from random import randint as ri
print [n for n in [ri(1,99) for i in range(9)] if n%2]
map():
map( (lambda x: x+2), [0, 1, 2, 3, 4, 5] )
带有多个序列的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)]
reduce():
>>> print 'the total is:', reduce( (lambda x,y: x+y), range(5) )
the total is: 10 #0+1+2+3+4=10
3 偏函数应用(PFA)
这种函数将任意数量(顺序)的参数的函数转化成另一个带剩余参数的函数对象
例子:
>>> 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(1)
2
>>> mul100(10)
1000
>>> baseTwo = partial(int, base=2)
>>> baseTwo.__doc__ = 'Convert base 2 string to an int.'
>>> baseTwo('10010')
18
这个例子使用了 int()内建函数并将 base 固定为2来指定二进制字符串转化。现在没有多次用相同的第二参数2来调用int (), 比如('10010', 2),而可以只用带一个参数的新 baseTwo()函数。
注意警惕关键字:
这个例子如果你创建了不带 base 关键字的偏函数,比如, baseTwoBAD = partial(int, 2),这可能 会让参数以错误的顺序传入 int(),因为固定参数的总是放在运行时刻参数的左边, 比如 baseTwoBAD(x) == int(2, x)。如果你调用它,它会将2作为需要转化的数字,而base 作为'10010' 来传入,然后就产生一个异常:
>>> baseTwoBAD = partial(int, 2) #词句和上面的区别就在于没有写base=2
>>> baseTwoBAD('10010')
Traceback (most recent call last): File "<stdin>", line 1, in <module>
TypeError: an integer is required
五 变量作用域
1 全局变量和局部变量
2 globa语句
为了明确地引用一个已命名的全局变量,须使用global修饰:
global var1
3 闭包
若在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是 closure。定义在外部函数内的但由内部函数引用或者使用的变量被称为自由变量。
简单闭包的例子:
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
4 作用域和lambda
python的lambda匿名函数遵循和标准函数一样的作用域规则。一个 lambda 表达式定义了新的作用域。
六 生成器
生成器是一个带 yield语句的函数。一个函数或者子程序只返回一次,但一个生成器能暂停执行并返回一个中间的结果----那就是 yield 语句的功能,返回一个值给调用者并暂停执行。当生成器的 next()方法被调用的时候,它会准确地从离开地方继续
简单的生成器特性:
def simpleGen():
yield 1
yield '2 --> punch!'
>>> myG = simpleGen()
>>> myG.next()
1
>>> myG.next()
'2 --> punch!'
>>> myG.next()
Traceback ( most recent call last ):
File "", line 1, in ?
myG.next() StopIteration
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
...
scissors
rock
paper
加强的生成器特性:
在 python2.5 中,一些加强特性加入到生成器中,所以除了next()来获得下个生成的值,用户可以将值回送给生成器,在生成器中抛出异常,以及要求生成器退出:
def counter(start_at=0):
count = start_at
while True:
val = (yield count)
if val is not None:
count = val
else:
count += 1
>>> count = counter(5)
>>> count.next()
5
>>> count.next()
6
>>> count.send(9)
9
>>> count.next()
10
>>> count.close()
Python核心编程读笔 10:函数和函数式编程的更多相关文章
- 【7】python核心编程 第十一章-函数和函数式编程
1.*函数(与方法)装饰器 装饰器背后的主要动机源自python 面向对象编程.装饰器是在函数调用之上的修饰.这些修饰 仅是当声明一个函数或者方法的时候,才会应用的额外调用. 装饰器的语法以@开头,接 ...
- python核心编程学习记录之函数与函数式编程
@func function 意思是func(function) @func(a) function 意思是func(a)这是个函数对象,在去调用function函数 如果要传额外的值,只传值用*tu ...
- 跟着ALEX 学python day3集合 文件操作 函数和函数式编程 内置函数
声明 : 文档内容学习于 http://www.cnblogs.com/xiaozhiqi/ 一. 集合 集合是一个无序的,不重复的数据组合,主要作用如下 1.去重 把一个列表变成集合 ,就自动去重 ...
- Python之路Python作用域、匿名函数、函数式编程、map函数、filter函数、reduce函数
Python之路Python作用域.匿名函数.函数式编程.map函数.filter函数.reduce函数 一.作用域 return 可以返回任意值例子 def test1(): print(" ...
- python学习7—函数定义、参数、递归、作用域、匿名函数以及函数式编程
python学习7—函数定义.参数.递归.作用域.匿名函数以及函数式编程 1. 函数定义 def test(x) # discription y = 2 * x return y 返回一个值,则返回原 ...
- python学习-day16:函数作用域、匿名函数、函数式编程、map、filter、reduce函数、内置函数r
一.作用域 作用域在定义函数时就已经固定住了,不会随着调用位置的改变而改变 二.匿名函数 lambda:正常和其他函数进行配合使用.正常无需把匿名函数赋值给一个变量. f=lambda x:x*x p ...
- day16_函数作用域_匿名函数_函数式编程_map_reduce_filter_(部分)内置函数
20180729 补充部分代码 20180727 上传代码 #!/usr/bin/env python # -*- coding:utf-8 -*- # ***************** ...
- 函数与函数式编程(生成器 && 列表解析 && map函数 && filter函数)-(四)
在学习python的过程中,无意中看到了函数式编程.在了解的过程中,明白了函数与函数式的区别,函数式编程的几种方式. 函数定义:函数是逻辑结构化和过程化的一种编程方法. 过程定义:过程就是简单特殊没有 ...
- day03 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数
本节内容 1. 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数 温故知新 1. 集合 主要作用: 去重 关系测 ...
随机推荐
- Bellman 算法
这道题目事实上就是在求有没有正环.与求负环的差别就是要不断的更新值,可是这个值要变大.而不是变小. Currency Exchange Time Limit: 1000MS Memory Limi ...
- Oracle11g重建EM 报ORA-20001: SYSMAN already exists
日志: Apr , :: PM oracle.sysman.emcp.EMReposConfig createRepository : SYSMAN already exists.. ORA-0651 ...
- JAVA Socket获取服务端信息
1.Socket.getInetAddress(),获取服务端地址. 2.Socket.getPort(),获取服务端端口.
- radio与checkbox
最近一直在学习Javascript与asp.net MVC4,每天都在跟着书学习.这样总感觉自己看的很抽象,没有点实际的意义.而且,每次看的东西很容易忘记,所以打算在这里记录自己的学习笔记. Java ...
- iOS设计模式解析(四)组合模式
组合模式:将对象组合成树形结构以表示"部分-整体"的层次结构.组合是的用户对单个对象和组合对象的使用具有一致 Cocoa Touch中组合模式使用:Cocoa Touch框架中,U ...
- 自学HTML5第三节(拖放效果)
今天来看看网页上的拖放效果,首先来看看什么是拖放———— 拖放 拖放是一种常见的特性,即抓取对象以后拖到另一个位置. 在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放. 浏览器支持 Inte ...
- 01UITextField基础知识
文字属性 文字属性包括:text; placeholder(默认使用70%灰色):font:textColor;textAligment. 文字大小 文字大小包括:adjustsFontSizeToF ...
- C语言 —— 括号配对问题(不使用栈)
最近在南阳理工的OJ上刷题,看到一个有点意思的题目 网上的答案大多都使用了栈,可惜我还没有学习数据结构,所以只能用简单的方法来解决 题目的链接在这 http://acm.nyist.net/Judge ...
- Spring包的方法WebUtils.getParametersStartingWith(request,String)
举个例子,比如页面上有 <input type="text" name="p_name" value="aileen"> < ...
- 了解单位em和px的区别
这里引用的是Jorux的“95%的中国网站需要重写CSS”的文章,题目有点吓人,但是确实是现在国内网页制作方面的一些缺陷.我一直也搞不清楚px与em之间的关系和特点,看过以后确实收获很大.平时都是用p ...