简体   繁体   中英

Python - Inner Functions, Closures, and Factory Functions - how to factor out?

I'm hoping a Python expert out there can offer some assistance on the confusion I'm experiencing currently with Inner Functions, Closures, and Factory Functions. Upon looking for an implemented example of a General Hough Transform I found this:

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

I'd like to translate this into C++ and it seems the first step is to factor out the inner function in 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

I seem to be stuck on how this function works. "f" does not seem to be called anywhere, and I'm not sure how the function knows what "query_image" is? I'v tried various Googling to find tips on Inner Functions, Closures, and Factory Functions, for example this and some similar pages, but all the examples I can find are more simplified and therefore not much help. Can anybody offer some direction?

The code is just returning the function f as a whole thing. There's no need to "know what the argument is" -- f will know it at the time it is called. The classic example is this:

>>> 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

Here, as in your function, g closes over another value ( x or r_table , respectively), while still expecting its actual argument.

Since there is a closed-over value, you cannot directly factor out f . One traditional approach is to return an object containing the value, which has some kind of call method representing the function; the easier way in C++ nowadays is to use a lambda function:

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

In C++ you have the "advantage" that it will yell at you if don't specify which values you are closing over (that's the [x] here). But internall, it does pretty much the same thing (constructing an anonymous class with an x -member).

C++ before C++11 does not have function as type.

You can use the following class to emulate the semantics (pseudo code):

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)
    }        
  }

Then, you can use it as follows:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM