0

In Python, functions are first-class objects, which means that one can pass and return them to and from other functions. This is a very interesting feature of the language, and I was wondering if there any classical examples where this is used in a significant way? Or are there any algorithms which use, or can be elegantly presented, using this feature?

Mike
  • 101
  • 3

3 Answers3

1

One of the greatest power of the function-passing is 'Closures'. A closure is data attached to code and the common use of that is:

  • Replacing hard coded constants
  • Eleminating globals
  • Providing consistent function signatures
  • Implementing Object Orientation

This is a really cool stuff, imagine you can bind variables to values within a function and then pass it. Whoever will complete the binding will initiate the function. You may refer to the following simple example:

def makeInc(x):
  def inc(y):
     # x is "attached" in the definition of inc
     return y + x

 return inc

incOne = makeInc(1)
incFive = makeInc(5)

incOne (5) # returns 6
incFive(5) # returns 10

Explanation: Closures in python are created by function calls. Here, the call to makeInc creates a binding for x that is referenced inside the function inc. Each call to makeInc creates a new instance of this function, but each instance has a link to a different binding of x.

Note: this answer was based on this page.

Gal Dreiman
  • 3,969
  • 2
  • 21
  • 40
0

Dependency injection is a classic. This means that I can do stuff like below, which allows you to push the decision making logic for which analysis_func to use further up the decision tree instead of having a bunch of logic in process_data. This can make it easier to reveal the underlying polymorphic nature of the code.

def process_data(data,analysis_func):
  prepped_data = prep_data(data)
  ...
  analyzed_data = analysis_func(prepped_data)
Canaryyellow
  • 157
  • 6
0

A nice example is a method validation_callback which is usefull in validators for wxpython's UI widgets.

class CMyClass( object ) :

    # An object attribute 
    self._my_attr = a_value
    # Define a validator for the widget self.textCtrl which is responsible for self._my_attr
    self.textCtrl.SetValidator \
        ( CMyValidator \
            ( obj       = self
            , attr_name = '_my_attr'
            , validation_callback = self.validation_callback
            )
        )

    # Define a validation callback method for validations which are specific for this class
    def validation_callback( self, value ) :
       # Do some validations specific to this class, e. g.
       if not self._pattern.match( value ) :
           # Does not match the reqular expression stored in self._pattern
           raise ValueError( myErrorValues )

The base class:

CValidatorBase( object ) :
    def __init__( self, obj, attr_name, validation_callback=None ) :
        # ....
        self._obj = obj
        self._attr_name = attr_name
        self._validation_callback = validation_callback
        # ....

The constructor of the base class CValidatorBase stores a reference to the method self._validation_callback() (if given, else it remains None) in an attribute CValidatorBase._validation_callback.

In this base class there could be a method validate() like this:

def validate( self, obj ) :

    # obj: the UI widget, get its value
    my_value = self.get_my_value_form_obj( obj )

    # First do some general validations
    # e. g. if the value is required it must not be an empty string etc.

    # then
    if self._validation_callback : # is there a validation callback defined?
        try : 
            #----------------------------------------
            self._validation_callback( my_value ) # this call is the answer of your question
            #----------------------------------------
        except ValueError, err: 
            # The validation_callback() should throw a ValueError-Exception (or another 
            # appropriate exception) in case of a validation error 
            # my_error_handler( obj, err )

As you see the attribute _validation_callback can contain whichever method is supplied from an inheriting class. The call self._validation_callback(my_value) is in fact a call to CMyClass.validation_callback(my_value).

Humbalan
  • 677
  • 3
  • 14