objects or closures - when to use?

I can define an object and assign attributes and methods:

class object:
    def __init__(self,a,b):
        self.a = a
        self.b = b
    def add(self):
        self.sum = self.a + self.b
    def subtr(self):
        self.fin = self.sum - self.b
    def getpar(self):
        return self.fin

obj = object(2,3)
obj.add()
obj.subtr()
obj.getpar()

or provide the same functionality by defining a closure:

def closure(a,b):
    par = {}
    def add():
        par.update({'sum':a+b})
    def subtr():
        par.update({'fin':par['sum']-b})
    def getpar():
        return par['fin']
    return {'add':add,'subtr':subtr,'getpar':getpar}

clos = closure(2,3)
clos['add']()
clos['subtr']()
clos['getpar']()

I think the object syntax would look cleaner to most viewers, but are there instances in which the use of a closure would be semantically preferable?

Answers


In Python, closures can be harder to debug and to use than the more usual objects (you have to save the callables somewhere, access them with the goofy notation clos['add'] etc, ...). Consider for example the impossibility of accessing the sum if you find something strange in the result... debugging this kind of thing can be really hard;-)

The only real compensating advantage is simplicity -- but it basically applies only to really simple cases (by the time you have three callables that are internal functions I'd say you're overboard in that respect).

Maybe the very strong protection (vs objects' protection "by convention" for class and instance objects), or the possible higher familiarity to Javascript programmers, might justify using closures rather than classes and instances in marginal cases, but in practice I haven't found myself in cases where such hypothetical advantages seemed to actually apply -- so I only use closures in really simple cases;-).


You should use the version that most clearly expresses what you are trying to achieve.

In the example given, I'd say that object version is more clear, since it seems to be modeling an object with state that changes. Looking at the code that uses the value, the object version seems to express the clear intent, whereas the closure version seems to have operations (the indexing and 'magic' strings) that are beside the point.

In Python, I would favor a closure based approach when what is needed is something that is mostly like a function, and perhaps needs to capture some state.

def tag_closure(singular, plural):
    def tag_it(n):
        if n == 1:
            return "1 " + singular
        else:
            return str(n) + " " + plural
    return tag_it

t_apple = tag_closure("apple", "apples")
t_cherry = tag_closure("cherry", "cherries");
print t_apple(1), "and", t_cherry(15)

This is perhaps a little clearer than the following:

class tag_object(object):
    def __init__(self, singular, plural):
        self.singular = singular
        self.plural = plural

    def tag(self, n):
        if n == 1:
            return "1 " + self.singular
        else:
            return str(n) + " " + self.plural

t_apple = tag_object("apple", "apples")
t_cherry = tag_object("cherry", "cherries");
print t_apple.tag(1), "and", t_cherry.tag(15)

As a rule of thumb: If the thing is really only a single function, and it is only capturing static state, then consider a closure. If the thing is intended to have mutable state, and/or has more than one function, use a class.

Another way to put it: If you are creating a dict of closures, you are essentially duplicating the class machinery by hand. Better to leave it to the language construct designed to do it.


The only real reason I can see for using closures is, if you want to a rather strong guarantee that the user of your object/closure doesn't have access to a hidden variable.

Something like this:

class Shotgun:
   def __init__(self):
       me = {}
       me['ammo'] = 2
       def shoot():
         if me['ammo']:
           me['ammo'] -= 1
           print "BANG"
         else:
           print "Click ..."
       self.shoot = shoot

s = Shotgun()
s.shoot()
s.shoot()
s.shoot()

The calling syntax for the class looks nicer and you can subclass classes. The closure also involves repeating all names you wish to expose in the return statement. Perhaps that is ok though if you want to have really private methods that are more hidden than the usual underscore prefix convention


I made a comment to the effect that using function attributes, a closure can utilize the same syntax as a class because functions are objects in python. All the internal variables also become accessible just like the class method.

I'm curious if this approach does Bad Things that I'm not aware of.

def closure(a, b):
    def add():
        closure.sum = a + b
    def subtr():
        closure.fin = closure.sum - b
    def getpar():
        return closure.fin
    closure.add = add; 
    closure.subtr = subtr
    closure.getpar = getpar
    return closure

clo = closure(2,3)
clo.add()
clo.subtr()
print(clo.getpar())
print(clo.sum)
print(clo.fin)

Need Your Help

Advice - How to implement the same code with different parameters

c# .net wpf enums

I would like an advice. My project have a lot of equals methods with different values, and i would like to do a single method that does the same.

Oracle: Avoiding NULL value in to_date

sql oracle date datetime to-date

I have a functional select statement that has a where clause, in the where clause there is a statement like so...