【问题标题】:What is the difference between a higher-order function and a class?高阶函数和类有什么区别?
【发布时间】:2021-04-29 15:59:46
【问题描述】:

我正在学习函数式编程的基础知识,最终遇到了高阶函数的概念。我在video by Corey Schafer(11:00 开始)中看到了一个示例,它显示了一个可以将消息包装在任意 HTML 标记中的 Python 函数:

def html_tag(tag):
    def wrap_text(msg):
        print('<{0}>{1}</{0}>'.format(tag, msg))

    return wrap_text

print_h1 = html_tag('h1')
print_h1('Test Headline!')
print_h1('Another Headline!')

print_p = html_tag('p')
print_p('Test Paragraph!')

输出:

<h1>Test Headline!</h1>
<h1>Another Headline!</h1>
<p>Test Paragraph!</p>

我知道它使您可以灵活地为不同目的(在本例中为不同的标签)重复使用相同的功能。但是您也可以使用 Python classes 获得相同的结果:

class HTML_tag:
    def __init__(self, tag):
        self.tag = tag
    
    def wrap_text(self, msg):
        print('<{0}>{1}</{0}>'.format(self.tag, msg))

print_h1 = HTML_tag('h1')
print_h1.wrap_text('Test Headline!')
print_h1.wrap_text('Another Headline!')

print_p = HTML_tag('p')
print_p.wrap_text('Test Paragraph!')

输出:

<h1>Test Headline!</h1>
<h1>Another Headline!</h1>
<p>Test Paragraph!</p>

高阶函数方法确实看起来更简洁,但除了美观之外,还有什么其他原因我可能更喜欢高阶函数而不是类?例如,关于诸如

之类的方面
  • 性能
  • 内存
  • ...

【问题讨论】:

  • 函数更容易组合成链式效果。如果你有一个HTML_tag 类,你可以通过使用适配器模式来实现类似的东西,但那是适配器并不是真正通用的,因为它们可以与HTML_tag 一起使用,不一定与XML_tagJSON_value 一起使用.
  • 你可以使用高阶函数来做很多事情。您可以计算一个函数需要多少时间来执行或动态添加属性到您的对象等。它们不会改变您的函数的实际行为,而是用一些功能装饰它。
  • 类是穷人的闭包。闭包是穷人的课程
  • @Asocia 好吧,装饰器是任何可调用的,它返回一个可调用的,正如您所说,“装饰”功能的某些方面。装饰器通常被实现为高阶函数,但并非总是如此,而且并非所有高阶函数都是装饰器。高阶函数就是任何将函数作为参数或返回函数的函数
  • 无论如何,是的,函数式编程是一种利用高阶函数的范式。这通常与使用类的命令式、面向对象的范例形成对比。请注意,函数式编程并不一定排除 OOP,请参阅 Scala 编程语言。但是,是的,这些是解决相同基本问题的不同方法

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


【解决方案1】:

高阶函数采用和/或返回函数。让我们看看这两种情况。

以函数为参数

在这里,HOF 绝对是要走的路。类版本相当于一个带有额外步骤的 HOF。对于类版本,您需要预先协商函数可调用的密钥。它实际上是你想要完成的内容的无用包装。

HOF

def my_map(fn, arr):
  result = []
  for a in arr:
    result.append(fn(a))
  return result

my_map(lambda a: a + 1, [1, 2, 3]) # [2, 3, 4]

类版本

def my_map(inst, arr):
  result = []
  for a in arr:
    result.append(inst.fn(a))
  return result

class my_mapper:
  def fn(self, a):
    return a + 1

my_map(my_mapper(), [1, 2, 3]) # [2, 3, 4]

返回一个函数

在这两个版本中,我们正在做的是创建一些值 a 的封装,以及在它上面工作的函数。

我认为,如果您希望在某些数据上定义多个函数,当封装的数据可以更改(您正在编码状态机),或者当您希望操作特定于您的班级(即您班级的用户需要知道在班级上定义的操作)。

当我所做的相当于部分应用时,我会使用一个返回函数的函数(我有一个带有多个参数的函数,我想预先应用一些参数,比如“add”)。我也会使用functools.partial 来做到这一点。

def adder(a):
  return lambda b: a + b
class adder_class:
  def __init__(self, a):
    self.a = a

  def add(self, b):
    return a + b

最终,最好使用 HOF 还是使用类将从上下文中变得清晰。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-05
    • 2016-07-06
    • 2012-08-11
    • 2012-04-25
    • 1970-01-01
    相关资源
    最近更新 更多