我希望能够定义一个python函数,它执行某种数据结构遍历并在每一步执行一些操作(在回调中定义)。这是一个简单的例子来说明。
def min_value(list):
m = 0
for i in range(0, len(list)):
if list[i] < m: m = list[i]
return m
这个例子很简单,但如果我遍历一个n维数组,一个numpy数组,或者我想定义一个更复杂的步进数据结构的方法,那就变得更复杂了。
我正在寻找一个&#34; pythonic&#34;类似于以下JavaScript做同样的事情。
traverse = function(list, callback) {
for(i = 0; i < list.length; i++) {
callback(list[i])
}
}
min_value = function(list) {
m = 0
traverse(list, function(element) {
if(element < m) m = element
});
}
如果我想要一个函数max_value(list)
,只需将一行调整为if(element > m) m = element
即可,而无需复制/粘贴遍历函数。在python中执行此操作的最佳方法是什么?
编辑(答案):在这里,我使用下面接受的答案来说明我的原始JS示例如何用python 3编写。有明显更好的方法来查找列表的最小值标量,但这是我正在寻找的模式。
def traverse(list, callback):
for i in range(0, len(list)):
callback(list[i])
def min_value(list):
m = 0
def update_min(val):
nonlocal m
if(val < m): m = val
traverse(list, update_min)
return m
编辑(复杂示例):这是我的用例的更复杂和直接的示例。我有一个图像,我想在焦点区域进行一些处理&#34;图像。让我们说,例如,我想找到图像中最暗的10x10,20x20,30x30等像素区域。我的图像是一个numpy数组。我会使用&#34; bastard&#34;多行lambda来说明我喜欢做什么,尽管据我所知,lambdas不能以这种方式使用。
在python中:
# find the coordinates and of darkest region
def darkest_region(image, fsize):
darkest_coords = [0, 0]
darkest_avg = 256
# illegal lambda
g = lambda x, y, r:
# r is an fsize x fsize region
avg_darkness = # blah blah, traverse and average pixels
if(avg_darkness < darkest_avg): darkest_coords = [x, y]
focus_scan(image, fsize, g)
return darkest_coords
# scan all regions of fsize x fsize
def focus_scan(image, fsize, callback):
height, width = image.shape[:2]
for y in range(0, height - fsize):
for x in range(0, width - fsize):
focus = image[y:y+fsize, x:x+fsize]
callback(x, y, focus)
鉴于我不能有这样的多行lambda,我认为我需要做的是对focus_scan
的参数和返回值有点看中,以适应各种各样的可能的输入/输出。在这个例子中,我可以传递焦点扫描darkest_avg
并让它返回我正在寻找的坐标,但是我可能想要传递除标量之外的其他东西,或者让它返回更复杂的数据结构。我想我必须做类似的事情:
def focus_scan(image, fsize, callback, args):
... # loopy loops
some_result = callback([x, y, focus], args)
return some_result
我喜欢我可以在其他编程语言中使用的内联函数方法,但它看起来并不像python中常见的模式。
答案 0 :(得分:3)
您可以完全将函数传递给函数,就像在JS中一样。
def myFancyTraversal(data, callback):
result = 0
for element in data: # or anything more fancy
result = callback(element, result)
return result
但在重新发明轮子之前,请确保您能够熟练使用list comprehensions,map
,reduce
和lambda
。
答案 1 :(得分:3)
只使用普通函数而不是多行lambda。要访问darkest_coords
变量,您可以在Python 3中使用nonlocal
关键字。在Python 2中,您必须改变列表,因为nonlocal
关键字不可用。
def darkest_region(image, fsize):
"""Find the coordinates of darkest region."""
darkest_coords = [0, 0]
darkest_avg = 256
def g(x, y, r):
nonlocal darkest_coords
# r is an fsize x fsize region
avg_darkness = # blah blah, traverse and average pixels
if avg_darkness < darkest_avg:
darkest_coords = [x, y]
focus_scan(image, fsize, g)
return darkest_coords
def focus_scan(image, fsize, callback):
"""Scan all regions of fsize x fsize."""
height, width = image.shape[:2]
for y in range(0, height - fsize):
for x in range(0, width - fsize):
focus = image[y:y+fsize, x:x+fsize]
callback(x, y, focus)
答案 2 :(得分:2)
对于您的情况,我只使用内置min
函数:
>>> min([1, 2, 3, 4, 5])
1
但是如果你想要一个内联函数,你可以使用lambda和map。 map
函数本质上是traverse
函数的内置版本。
def findMin(arr):
m = 100 #Must be a value larger than can be in your list
min_func = lambda el: el if el < m else m #Use an inline lambda to declare a function.
for val in map(min_func, arr): #Returns the function called on
#every item in the array
m = val #Set m to the new lowest value
return m
min_func
lambda相当于:
def min_func(el):
if el < m:
return el
return m