通过闭包将参数封装至函数内从而通过map调用
事件的开始是希望使用 map
函数对一个列表进行split
操作。遇到的问题是split
是一个str
对象的方法,通常的用法是s.split
, 其中s
是一个str
类的实例。而向map
中传入的应该是一个函数的名称,而不能绑定到一个具体的实例上。解决方法是
fun = str.split
接下来遇到了第二个问题,split默认的分割符默认是''
,而改变分隔符需要向方法中传入参数,而传入参数需要用()
调用方法,这与map
中需要的函数名称不兼容。我想到的一个解决方法是使用闭包。闭包的定义大概是这样的
如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure).
利用闭包,可以将一些参数封装到函数之中比如
def fun(x):
def split1(self):
str.split(self, '%c' % x)
return
return split1
a = fun('\t')
通过调用fun
函数,可以将分隔字符串用的转义字符封装在split1
函数中,这样在使用map
进行调用时,可以不通过调用而添加参数。
map(split1, seq)
从而达到利用map
函数将列表中的字符串批量的分隔。
map函数与列表解析
列表解析是一种可以快速生成列表的方法,其语法是:
[expr for iter_var in iterable]
[expr for iter_var in iterable if cond_expr]
列表解析不仅可以用来生成列表这种一维结构,实际上任意维都可以:
(x, y) for x in iter for y in iter
那么列表解析和map
函数有什么关系呢?map
函数实际上也是一种可以对表列进行批量操作的函数,用法:
map(func, seq[,seq])
当参数中只用一个序列时,即对序列的每一项进行映射。当参数中有一个以上的序列时,将取每个序列中下表相同的项进行映射并将结果组成一个元组作为结果列表的一项。与列表解析的不同是map
函数并不遍历几个序列的所用组合(列表解析是这样),只取下表相同的组合。
闭包与作用域
推荐文章 Python 里为什么函数可以返回一个函数内部定义的函数?
这个回答很清楚的解释了什么是闭包及作用域的问题,另外我还在这个回答中发现了一个很有用的网站VISUALIZE python,在这个网站上可以将代码执行的过程可视化,加深对代码的理解。通过这个回答,我理解了在另一个解释闭包的帖子中的一段代码
origin = [0, 0] # 坐标系统原点
legal_x = [0, 50] # x轴方向的合法坐标
legal_y = [0, 50] # y轴方向的合法坐标
def create(pos=origin):
def player(direction,step):
# 这里应该首先判断参数direction,step的合法性,比如direction不能斜着走,step不能为负等
# 然后还要对新生成的x,y坐标的合法性进行判断处理,这里主要是想介绍闭包,就不详细写了。
new_x = pos[0] + direction[0]*step
new_y = pos[1] + direction[1]*step
pos[0] = new_x
pos[1] = new_y
#注意!此处不能写成 pos = [new_x, new_y],原因在上文有说过
return pos
return player
player = create() # 创建棋子player,起点为原点
print player([1,0],10) # 向x轴正方向移动10步
print player([0,1],20) # 向y轴正方向移动20步
print player([-1,0],10) # 向x轴负方向移动10步
输出是
[10, 0]
[10, 20]
[0, 20]
自己看的时候一直没有明白棋子上一步的位置信息是怎么保存下来的,在可视化过这段代码后我发现pos
和origin
指向的是同一个地方。我想起了在python中引用和实体的关系,才明白了这段代码的工作方式。
下一篇再具体写作用域、命名空间等问题。