可组合性:迭代器与 Lambda

问题描述 投票:0回答:1

我无法理解“良好”功能可组合性的概念。假设使用以下方法删除具有特定扩展名的文件:

使用 Lambda 函数:

def traverse_tree(
        temp_storage: Local, extensions: List[str], is_raw: bool, operation: Callable
):
    for folder_path, subfolders, filenames in os.walk(temp_storage.root_path(is_raw)):
        for filename in filenames:
            base, ext = os.path.splitext(filename)
            if ext in extensions:
                file_path = os.path.join(folder_path, filename)
                operation(file_path)

def clear_temp(
        temp_storage, extensions: List[str], is_raw
):
    traverse_tree(temp_storage=temp_storage, extensions=extensions, is_raw=True, operation=lambda x: os.remove(x))

使用迭代器:

def traverse_tree(
        temp_storage, extensions: List[str], is_raw
):
    for folder_path, subfolders, filenames in os.walk(temp_storage.root_path(is_raw)):
        for filename in filenames:
            base, ext = os.path.split(filename)
            if ext in extensions:
                file_path = os.path.join(folder_path, filename)
                yield file_path


def clear_temp(
        temp_storage: Local, extensions: List[str], is_raw: bool
):
    for path in traverse_tree(temp_storage, extensions, is_raw):
        os.remove(path)

在模块化和易于调试方面,一种方法是否比另一种方法更受青睐?如果是这样,您能否举一个例子,其中一种方法客观上会导致灵活性降低?

谢谢,

python design-patterns functional-programming composable
1个回答
0
投票

您的问题与函数可组合性无关 - 您没有组合函数。

您似乎很难证明是否需要

operation: Callable
以及它有什么用处(如果有的话)。您的示例的问题在于它过于简单化。如何添加与任意复杂模式匹配的(某些)文件的重命名?您是否会复制/粘贴完全相同的代码的另一个版本,唯一的区别在于实现
for
的循环体

实现它的一种(非常常见且经过实践证明是合理的)方法是

从中提取高阶函数并将其作为参数。这种技巧在像古老的 C 这样的语言中效果不佳,在这种语言中,你不能将类型良好的(如果只有 C 有一些类型良好的话......)函数作为第一类对象,并且没有匿名函数(也称为“lambda” - 来自 lambda 演算 的术语)。但 Python 确实拥有它——就像许多其他现代语言一样!

有了这一点,您可以“重用”同一段代码,并使其具有多态性,直至实现它所采用的所有(函数)参数。更重要的是,这正是像 Haskell 这样被广泛认可的“纯函数式”编程语言构建代码库的方式,特别是它们的标准库。这种方法的另一个很好的例子是 Python 的

iteratorfilter

 - 两者都希望您提供一个执行过滤/映射的函数,以便 
单个实现
 可以很好地处理迭代本身。

© www.soinside.com 2019 - 2024. All rights reserved.