-1

How it is possible to create variable on function in below example? Can anyone please explain about this possibility in wrapper.count?

def logging_decorator(func):
    def wrapper():
        wrapper.count += 1
        print "The function I modify has been called {0} times(s).".format(
              wrapper.count)
        func()
    wrapper.count = 0
    return wrapper

def a_function():
    print "I'm a normal function."

modified_function = logging_decorator(a_function)

modified_function()
# >> The function I modify has been called 1 time(s).
# >> I'm a normal function.

modified_function()
# >> The function I modify has been called 2 time(s).
# >> I'm a normal function.
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Bee..
  • 195
  • 1
  • 8

1 Answers1

1

Python is an object-oriented language through-and-through - a function is just another object instance * (also referred to as "first class objects" - see this question):

>>> def myfunc():
    pass

>>> type(myfunc)
<type 'function'>

and has a __dict__ of its attributes:

>>> myfunc.__dict__
{}

Therefore you can add an attribute to a function, as you can to any other class instances with a __dict__ **:

>>> myfunc.foo = "bar"
>>> myfunc.__dict__
{'foo': 'bar'}

Another example of this is the classic memoizer, where a cache dictionary attribute is added to the function returned by a decorator:

def memoize(f):
    def func(*args):
        if args not in func.cache:
            func.cache[args] = f(*args)
        return func.cache[args]
    func.cache = {}
    return func

* This is not true of built-in functions, which are <type 'builtin_function_or_method'> - for example, you can't add an attribute to max.

** Not all instances have a __dict__ - for example, instances of the built-in types like int and str don't, so you can't add attributes to those, either.

Community
  • 1
  • 1
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437