cmjdxy
cmjdxy

Reputation: 396

Difference between closure and decorator in Python

This is a program to compute factorial number with cache.

def run_closure():
    f = cache(factorial)
    print("5! = %d" % f(5))
    print("5! = %d" % f(5))
    print("4! = %d" % f(4))
    pass


def run_decorator():
    print("5! = %d" % factorial(5))
    print("5! = %d" % factorial(5))
    print("4! = %d" % factorial(4))
    pass


def cache(func):
    table = {}
    def wrapper(n):
        if n in table:
            print("%d is in memo." % n)
            return table[n]
        else:
            print("f(%d) is called." % n)
            table[n] = func(n)
            return table[n]
    return wrapper


# @cache # comment for "run_closure()"; uncomment for "run_decorator" 
def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n - 1)


def main():
    run_closure()
    # run_decorator()
    pass

if __name__ == "__main__":
    main()
    pass

I implement this by means of closure and decorator. The former output:

f(5) is called.
5! = 120
5 is in memo.
5! = 120
f(4) is called.
4! = 24

The latter output:

f(5) is called.
f(4) is called.
f(3) is called.
f(2) is called.
f(1) is called.
f(0) is called.
5! = 120
5 is in memo.
5! = 120
4 is in memo.
4! = 24

In the former case, when 5! is computed, the previous n!(n<5) should have been computed and saved into table but it didn't. The latter case is what I want. So what's the difference between closure and decorator? Any help is appreciated.

Upvotes: 1

Views: 1720

Answers (2)

shivesh kumar
shivesh kumar

Reputation: 85

Decorators, in the general sense, are functions or classes that wrap around another object, that extend or decorate the object. The decorator supports the same interface as the wrapped function or object, so the receiver doesn't even know the object has been decorated.

A closure is an anonymous function that refers to its parameters or other variables outside its scope.

So basically, decorators use closures, and not replace them.

Upvotes: 1

STerliakov
STerliakov

Reputation: 7877

Using decorator, you change the function itself, and its new version is called recursively. When using closure on the way you do it behaves different: you create function f, which internally keeps calling factorial. If you set factorial=cache(factorial), it will behave exactly the same as decorated does.

Upvotes: 2

Related Questions