我想使用函数process_slide_index(x)
tiles_index:
[(1, 1024, 0, 16, 0, 0), (1, 1024, 0, 16, 0, 1), (1, 1024, 0, 16, 0, 2), (1, 1024, 0, 16, 0, 3), (1, 1024, 0, 16, 0, 4), (1, 1024, 0, 16, 0, 5), (1, 1024, 0, 16, 0, 6),...]
瓷砖:
tiles = map(lambda x: process_slide_index(x), tiles_index)
地图功能:
def process_slide_index(tile_index):
print("PROCESS SLIDE INDEX")
slide_num, tile_size, overlap, zoom_level, col, row = tile_index
slide = open_slide(slide_num)
generator = create_tile_generator(slide, tile_size, overlap)
tile = np.asarray(generator.get_tile(zoom_level, (col, row)))
return (slide_num, tile)
我正在应用map函数,但似乎没有进入process_slide_index(tile_index)
函数内部。
我还想过滤某些返回给定True
中的False
的函数的结果。但是我的功能再次没有达到过滤器功能。
filtered_tiles = filter(lambda x: keep_tile(x, tile_size, tissue_threshold), tiles)
我在做什么错了?
致谢
编辑,我到达该检查点消息PROCESS SLIDE INDEX
的唯一方法是在 tiles 行之后添加list(map(print, tiles))
。我用它来尝试调试,并且我的照片开始出现。我现在很困惑。
答案 0 :(得分:3)
您正在使用python3
,在 python2 map
和filter
中返回列表,但在 python3 中它们返回一个对象您必须消耗才能获得值:
>>> l = list(range(10))
>>> def foo(x):
... print(x)
... return x+1
...
>>> map(foo, l)
<map object at 0x7f69728da828>
要使用此对象,例如可以使用list
。注意这次print
的调用方式:
>>> list(map(foo, l))
0
1
2
3
4
5
6
7
8
9
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
该对象是惰性的,这意味着它们yield
一个个地{1}。在for
循环中将它们用作迭代器时,请检查差异:
>>> for e in map(foo, l):
... print(e)
...
0
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
使用list
的功能相同,但是将每个采用的值存储在该列表中。
答案 1 :(得分:1)
您应该从map
调用中删除lambda。 map
将调用第一个参数中提供的函数,并且您已经为实际要调用的函数提供了包装函数。
tiles = map(process_slide_index, tiles_index)
答案 2 :(得分:0)
TL; DR-
列表理解可以在这里完成很多您可能想要的事情。 [x for x in mylist if x > y]
是一个功能强大的表达式,不仅可以代替filter()
。它也是map()
的不错选择,并且比使用lambda表达式更有效。它还会列出一个列表,而不是生成器,这在您的情况下可能更可取。 (如果要处理巨大数据流,则可能要坚持使用map
和filter
,因为使用生成器时,您不必保留全部内容在RAM中,您可以一次计算一个值。)如果您喜欢这个建议,但想跳过话题,我会在 2b 中给您提供代码。
不要为已经存在的函数编写lambda表达式! Lambda表达式是尚未定义的替代函数。它们慢得多,并且有一些奇怪的行为。尽可能避免它们。您可以将map()
调用中的lambda替换为函数本身:tiles = map(process_slide_index, tiles_index)
长版:
有两个问题,两个都很容易解决。第一个更多的是样式/效率问题,但它也可以为您省去一些难以理解的麻烦:
1。。最好不要使用lambda表达式,而最好使用已经用于定义工作的函数!
tiles = map(process_slide_index, tiles_index)
做得很好,并且表现更好。
2。。您可能应该切换到列表理解。为什么?因为map()
和filter()
较丑陋,因此如果您必须使用lambda或以后想要将输出转换为列表,则它们会较慢。不过,如果您坚持使用map()
和filter()
...
2a。。当您需要将多个参数传递给map函数时,如果您提前知道许多值,请尝试functools.partial
。我认为尝试时是逻辑错误
filtered_tiles = filter(lambda x: keep_tile(x, tile_size, tissue_threshold), tiles)
您要说的是在保持keep_tile()
和[x for x in tiles]
不变的情况下,在向量tile_size
上调用tissue_threshold
。
如果这是预期的行为,请尝试import functools
并使用functools.partial(keep_tile, tile_size, tissue_threshold)
。
注意:使用functools.partial
要求传递给部分函数的任何变量都是最右边的参数,因此您必须将函数标头重写为def keep_tile(tile_size, tissue_threshold, tiles):
而不是def keep_tile(tiles, tile_size, tissue_threshold):
。 (请参见我们再次设法避免使用lambda表达式!)
如果这不是预期的行为,并且您希望每个调用中的每个值都发生变化,则只需传入一个元组即可! filter(keep_tile, (tile, tile_size, tissue_threshold)))
。如果您只想从中使用tile
变量,则可以使用列表理解:
[x[0] for x in filter(keep_tile, (tile, tile_size, tissue_threshold)))]
(同样,没有lambda。)但是,由于我们已经在此处进行列表理解,因此您可能想在 2b中尝试该解决方案。
2b。。通常,在更高版本的Python中,仅使用列表推导(例如[x[0] for x in tiles if keep_tile(*x)]
)会更快,更干净。 (或者,如果要使其他两个值保持不变,则可以使用[x for x in tiles if keep_tile(x, tile_size, tissue_threshold)]
。)任何时候,只要将map()
或filter()
的输出读取为之后,您可能应该使用列表理解。此时,map()
和filter()
实际上仅对通过管道流式传输结果或异步例程有用。