Is it beneficial to replace a simple Python class with a closure?

Question:

I have the following Python class:

class class A:
    """a class that increments internal variable"""
    def __init__(self, x):
        self._x = x
    def incr(self):
        self._x = (self._x + 1) % 10
        return self._x

I heard a talk that recommended that such classes with just a constructor and another method really should just be replaced by a function.

So here is my attempt (for Python 2.7):

def incrX(x): 
    """closure that increments internal variable"""
    d = {'x' : x}
    def incr():
        d['x'] = (d['x'] + 1) % 10
        return d['x'] 
    return incr

Running it:

def test1():
    """testing closure vs. class"""
    print 'class...'
    a = A(10)
    print a.incr()
    print a.incr()

    print 'closure...'
    incr = incrX(10)
    print incr()
    print incr()

$ python closure.py 
running closure experiments
class...
1
2
closure...
1
2

So my question is:

Is there a benefit to replacing a class like A with a closure? Just trying to understand closures better.

Asked By: M-V

||

Answers:

The real benefit of closures and higher-order functions is that they can represent what the programmer sometimes has in mind. If you as the programmer find that what you have in mind is a piece of code, a function, an instruction on how to compute something (or do something), then you should use a closure for this.

If, on the other hand, what you have in mind is more like an object, a thing (which happens to have some properties, methods, instructions, capabilities, etc.), then you should program it as an object, a class.

In your case I think the best way to implement this is neither 😉 I’d do this with a generator:

def incrX(i):
  while True:
    i += 1
    i %= 10
    yield i

incr = incrX(10)
print incr.next()
print incr.next()
Answered By: Alfe

With a closure, one can save the self variable. In particular, when there are many variables to be passed, a closure could be more readable.

class Incr:
    """a class that increments internal variable"""
    def __init__(self, i):
        self._i = i
    def __call__(self):
        self._i = (self._i + 1) % 10
        return self._i
def incr(i): 
    """closure that increments internal variable"""
    def incr():
        nonlocal i
        i = (i + 1) % 10
        return i
    return incr
print('class...')
a = Incr(10)
print(a())   # 1
print(a())   # 2

print('closure...')
b = incr(10)
print(b())   # 1
print(b())   # 2

Answered By: Friedrich

closure binds data to functions in a weird way. on the other side, data classes try to separate data from functions. To me both of them are bad design. Never use them. OO(class) is a much more convient and natural way.

Answered By: Zhemin Zhu
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.