【问题标题】:Advantages of Higher order functions in PythonPython中高阶函数的优点
【发布时间】:2019-11-14 16:40:18
【问题描述】:

为了实现美化xml,我编写了以下代码

def prettify_by_response(response, prettify_func):
    root = ET.fromstring(response.content)
    return prettify_func(root)

def prettify_by_str(xml_str, prettify_func):
    root = ET.fromstring(xml_str)
    return prettify_func(root)

def make_pretty_xml(root):
    rough_string = ET.tostring(root, "utf-8")
    reparsed = minidom.parseString(rough_string)
    xml = reparsed.toprettyxml(indent="\t")
    return xml

def prettify(response):
    if isinstance(response, str) or isinstance(response, bytes):
        return prettify_by_str(response, make_pretty_xml)
    else:
        return prettify_by_response(response, make_pretty_xml)

在 prettify_by_response 和 prettify_by_str 函数中,我将函数 make_pretty_xml 作为参数传递

我可以简单地调用该函数,而不是将函数作为参数传递。例如

def prettify_by_str(xml_str, prettify_func):
   root = ET.fromstring(xml_str)
   return make_pretty_xml(root)

将函数作为参数传递给这些函数而不是直接调用该函数的优点之一是,该函数与 make_pretty_xml 函数不紧密耦合。

还有什么其他优势或者我是否增加了额外的复杂性?

【问题讨论】:

  • 提示,你可以用isinstance(response, (str,bytes))替换if

标签: python functional-programming higher-order-functions


【解决方案1】:

这似乎很容易接受有偏见的答案。我会尽量做到不偏不倚,但我不能做出任何承诺。

首先,高阶函数是接收和/或返回函数的函数。优点值得商榷,我会试着列举一下HoF的用法,并说明各自的优劣

回调

回调是一种阻止呼叫的解决方案。我需要B 发生在A 之后,所以我调用了阻止A 的东西,然后调用B。这自然会导致类似的问题,嗯,我的系统浪费了大量时间等待事情发生。如果不是等待,我可以将我需要完成的事情作为参数传递怎么办。因为任何尚未扩展的新技术在扩展之前似乎都是一个好主意。

回调在事件系统中非常常见。如果您使用 javascript 中的每个代码,您就会知道我在说什么。

算法抽象

一些设计,主要是行为设计​​,可以利用 HoF 在运行时选择一些算法。您可以拥有一个高级算法来接收处理低级内容的函数。这导致更多的抽象代码重用和可移植代码。在这里,可移植意味着您可以编写代码来处理新的低级别,而无需更改高级别。这与 HoF 无关,但可以利用它们提供很大帮助。

将行为附加到另一个函数

这里的想法是将一个函数作为参数并返回一个函数,该函数与参数函数所做的完全相同,另外还有一些附加的行为。这就是(我认为)HoF 真正闪耀的地方。

Python 装饰器就是一个很好的例子。它们将一个函数作为参数并返回另一个函数。该函数与第一个函数的标识符相同

@foo
def bar(*args):
   ...

是一样的

def bar(*args):
    ...
bar = foo(bar)

现在,反思一下这段代码

from functools import lru_cache

@lru_cache(maxsize=None)
def fib(n):
    if n < 2:
        return n
    return fib(n-1) + fib(n-2)

fib 只是一个斐波那契函数。它计算斐波那契数到n。现在lru_cache 附加一个新的行为,缓存之前已经计算的值的结果。 fib 函数内部的逻辑不受 LRU 缓存逻辑的污染。我们这里有多么美丽的抽象。

应用式编程或无点编程

这里的想法是删除变量或点并结合函数应用程序来表达算法。我敢肯定有很多人比我在这个主题上徘徊SO。

顺便说一句,这在 python 中不是很常见的样式。

for i in it:
    func(i)
from functools import partial

mapped_it = map(func, it)

在第二个示例中,我们删除了 i 变量。这在解析领域很常见。作为另一个侧节点,map 函数在 python 中是惰性的,因此第二个示例在您迭代 mapped_it 之前不会生效

您的情况

在您的情况下,您正在返回回调调用的值。实际上,您不需要回调,您可以像以前一样简单地排列调用,对于这种情况您不需要 HoF。

我希望这会有所帮助,并且有人可以展示更好的应用风格示例:)

问候

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-25
    • 1970-01-01
    • 2022-01-07
    • 2022-01-07
    • 1970-01-01
    • 2016-05-07
    相关资源
    最近更新 更多