【问题标题】:Python - Inner Functions, Closures, and Factory Functions - how to factor out?Python - 内部函数、闭包和工厂函数 - 如何分解?
【发布时间】:2017-04-23 11:11:21
【问题描述】:

我希望 Python 专家可以为我目前在使用内部函数、闭包和工厂函数时遇到的困惑提供一些帮助。在寻找通用霍夫变换的实现示例时,我发现了这一点:

https://github.com/vmonaco/general-hough/blob/master/src/GeneralHough.py

我想把它翻译成 C++,看来第一步是在 general_hough_closure() 中分解出内部函数:

def general_hough_closure(reference_image):
    '''
    Generator function to create a closure with the reference image and origin
    at the center of the reference image

    Returns a function f, which takes a query image and returns the accumulator
    '''
    referencePoint = (reference_image.shape[0]/2, reference_image.shape[1]/2)
    r_table = build_r_table(reference_image, referencePoint)

    def f(query_image):
        return accumulate_gradients(r_table, query_image)

    return f

我似乎对这个功能的工作方式感到困惑。 “f”似乎没有在任何地方被调用,我不确定该函数如何知道“query_image”是什么?我尝试了各种谷歌搜索来查找有关内部函数、闭包和工厂函数的提示,例如 this 和一些类似的页面,但我能找到的所有示例都更加简化,因此没有太大帮助。有人可以提供一些方向吗?

【问题讨论】:

  • 这段代码返回一个函数。你确定那是你想要的吗?我怀疑这是你想在 C++ 中做的事情。
  • @Rawing,我知道该函数返回一个函数,这是我想排除的部分,所以我可以翻译成 C++
  • 删除def f(query_image):这一行,删除return f,并给函数一个名为query_image的第二个参数。这应该很容易翻译。

标签: python


【解决方案1】:

代码只是返回函数f作为一个整体。没有必要“知道参数是什么”——f 会在它被调用时知道它。经典的例子是这样的:

>>> def f(x):
...     def g(y):
...         return x + y
...     return g
... 
>>> f
<function f at 0x7f8500603ae8>
>>> f(1)
<function f.<locals>.g at 0x7f8500603a60>
>>> s = f(1)
>>> s(2)
3

在这里,就像在您的函数中一样,g 关闭另一个值(分别为xr_table),同时仍然期待它的实际参数。

由于存在封闭值,因此您不能直接分解f。一种传统的方法是返回一个包含该值的对象,该对象具有某种表示函数的调用方法;现在在 C++ 中更简单的方法是使用 lambda 函数:

int f(int x) {
  auto g = [x](int y) {
    return x + y
  };
  return g;
}

在 C++ 中,如果不指定要关闭的值(这里是 [x]),它会向你大喊大叫。但在内部,它做的事情几乎相同(使用x-member 构造一个匿名类)。

【讨论】:

  • 如果我的 C++ 格式不正确,请直接编辑它,我实际上并不经常使用 C++。
【解决方案2】:

C++11 之前的 C++ 没有函数作为类型。

您可以使用以下类来模拟语义(伪代码):

class GeneralHoughClosure {
  public:
    GeneralHoughClosure(reference_image) {
      referencePoint = (reference_image.shape[0]/2, reference_image.shape[1]/2)
      r_table = build_r_table(reference_image, referencePoint)
    }
    void Run(queryImage) {
      return accumulate_gradients(r_table, query_image)
    }
    void operator()(queryImage) {
      return accumulate_gradients(r_table, query_image)
    }        
  }

那么,你可以按如下方式使用它:

gg = new GeneralHoughClosure(reference_image)
gg.Run(queryImage1)
gg(queryImage2)

【讨论】:

  • 感谢您的建议,有没有一种方法可以在不添加类的情况下分解嵌套函数?
  • C++11 确实具有作为类型的函数。你可以返回一个 std::function 初始化(例如)使用 lambda,就像在 python 中一样。
  • 你说得对,我更新了答案。我们中的一些人没有使用 C++11 的奢侈 :-)
  • 感谢您的建议,但我正在尝试在不使用类、返回 std::function 或使用 lambda 的情况下转换为 C++,关于如何完成此操作的任何建议?跨度>
猜你喜欢
  • 1970-01-01
  • 2012-08-18
  • 2021-10-26
  • 2017-01-06
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多