Python decorator function execution - python

I have below decorator demonstration code. If I execute it without explicitly calling greet function, it is executing print statement inside decorator function and outputs Inside decorator.
I am unable to understand this behavior of decorator. How the time_decorator is called even if I didn't call greet function?
I am using Python 3.
def time_decorator(original_func):
print('Inside decorator')
def wrapper(*args, **kwargs):
start = time.clock()
result = original_func(*args, **kwargs)
end = time.clock()
print('{0} is executed in {1}'.format(original_func.__name__, end-start))
return result
return wrapper
#time_decorator
def greet(name):
return 'Hello {0}'.format(name)

Decorators are called at start time (when the python interpreter reads the code as the program starts), not at runtime (when the decorated function is actually called).
At runtime, it is the wrapped function wrapper which is called and which itself calls the decorated function and returns its result.
So this is totally normal that the print line gets executed.
If, i.e, you decorate 10 functions, you will see 10 times the print output. No need to even call the decorated functions for this to happen.
Move the print inside wrapper and this won't happen anymore.
Decorators as well as metaclasses are part of what is called meta-programming (modify / create code, from existing code). This is a really fascinating aspect of programming which takes time to understand but offers amazing possibilities.

time_decorator is executed during function decoration. wrapper is not (this is function invoked when decorated greet() is called).
# is just syntactic sugar. Following code snippets are equivalent.
Decorator syntax:
#time_decorator
def greet(name):
return 'Hello {0}'.format(name)
Explicit decoration process - decorator is a function that returns new function based on another one.
def greet(name):
return 'Hello {0}'.format(name)
greet = time_decorator(greet)

Related

Why does a decorated function only return its value once all the decorated functions that are using that decorator are done? [duplicate]

I hope that someone familiar with Python's compilation / run-time procedures could shed some light on my question relating to how Python compiles decorator functions.
Within my sample code, I've included a testing print statement in the "writeit" decorator just before the logtofile closure is defined. If you run the entire code that I've provided, the "testing" print statement in writeit is called for each #writeit decorator defined in the Customer class-- before writeit is ever used.
Why is logtofile being called at compile time? Could someone please explain this behavior?
def writeit(func):
print('testing')
def logtofile(customer, *arg, **kwargs):
print('logtofile')
result = func(customer, *arg, **kwargs)
with open('dictlog.txt','w') as myfile:
myfile.write(func.__name__)
return result
return logtofile
class Customer(object):
def __init__(self,firstname,lastname,address,city,state,zipcode):
self._custinfo = dict(firstname=firstname,lastname=lastname,address=address,city=city,state=state,zipcode=zipcode)
#writeit
def setFirstName(self,firstname):
print('setFirstName')
self._custinfo['firstname']=firstname
#writeit
def setLastName(self,lastname):
print('setLastName')
self._custinfo['lastname']=lastname
#writeit
def setAddress(self,address):
print('setAddress')
self._custinfo['address']=address
def main():
cust1 = Customer('Joe','Shmoe','123 Washington','Washington DC','DC','12345')
cust1.setFirstName('Joseph')
cust1.setLastName('Shmoestein')
if(__name__ == '__main__'): main()
Your code runs when the module is imported. Python executes all top-level statements, including class definitions at that time.
A class definition body is executed as a function, with the local namespace becoming the class attributes. This means that class bodies are executed on import, provided the class is defined at the top-level of the module.
When Python encounters a decorated function when executing, it'll define the class, then execute the decorator function, passing in the function object and binding the return value of the decorator to the name of the function. Since the class body is executed during import, this means your decorator is executed at that time.
There is no compile time. A def statement, and the associated decorator calls are executable statements.
Accordingly, when Python loads a module, it executes the statements in order. When executing a class statement, one of the early stages is executing all of the statements in the class body. As part of that defs are run to create functions, and those function objects will be passed to decorators for processing.
Your "testing" print statement will run whenever the decorator is called, not when the function it returns is called. If you want that behaviour, move the decorator into the inner function.

Function Decorators in Python

I am a beginner in python and I am trying to wrap my head around function decorators in python. And I cannot figure out how functions return functions.
I mean in what order does interpreter interprets this function:
def decorator(another_func):
def wrapper():
print('before actual function')
return another_func()
print('pos')
return wrapper
And what is the difference between these 2 statements:-
return wrapper
AND
return wrapper()
I am using Head First Python, but this topic I feel is not described very well in there, please suggest any video or a good resource so that I can understand it.
The key to understanding the difference is understanding that everything is an object in python, including functions. When you use the name of the function without parenthesis (return wrapper), you are returning the actual function itself. When you use parenthesis, you're calling the function. Take a look at the following example code:
def foo(arg):
return 2
bar = foo
baz = foo()
qux = bar()
bar()
If you print baz or qux, it will print two. If you print bar, it will give you the memory address to reference the function, not a number. But, if you call the function, you are now printing the results of th
I cannot figure out how functions return functions.
As already explained by LTheriault, in python everything is an object. Not only this, but also everything happens at runtime - the def statement is an executable statement, which creates a function object from the code within the def block and bind this object to the function's name in the current namespace - IOW it's mostly syntactic sugar for some operations you could code manually (a very welcome syntactic sugar though - building a function object "by hand" is quite a lot of work).
Note that having functions as "first-class citizens" is not Python specific - that's the basis of functional programming.
I mean in what order does interpreter interprets this function:
def decorator(another_func):
def wrapper():
print('before actual function')
return another_func()
print('pos')
return wrapper
Assuming the decorator function is declared at the module top-level: the runtime first takes the code block that follows the def statement, compiles it into a code object, creates a function object (instance of type 'function') from this code object and a couple other things (the arguments list etc), and finally binds this function object to the declared name (nb: 'binds' => "assigns to").
The inner def statement is actually only executed when the outer function is called, and it's executed anew each time the outer function is called - IOW, each call to decorator returns a new function instance.
The above explanation is of course quite simplified (hence partially inexact), but it's enough to understand the basic principle.

Curious as to what the interpreter is doing here

I was working through a decorator design pattern tutorial
(credit to Jungwoo Ryoo)
I'm curious as to why I can swap the lines: return decorator
and print(hello_world()) with return decorator() and print(hello_world)
from functools import wraps
def make_blink(function):
"""Defines the decorator"""
#wraps(function)
# Define the inner function
def decorator():
# Grab the return value of the function being decorated
ret = function()
# Add new functionality to the function being decorated
return "<blink>"+ ret + "<b/link>"
return decorator #return decorator()#<THIS LINE HERE SWAPPED
# Apply the decorator here!
#make_blink
def hello_world():
"""Original function! """
return "Hello, World!"
# Check the result of decorating
print(hello_world()) #print(hello_world) #<THIS LINE HERE SWAPPED
Wouldn't the interpreter be doing something different each time? I'm just looking for some insight to have a better understanding of what's going on
Decorators are just functions really, and functions are just objects.
The lines
#make_blink
def hello_world():
# ...
are essentially the same as
def hello_world():
# ...
hello_world = make_blink(hello_world)
except the function object is never assigned to hello_world first (it's on the stack for to be passed to the decorator).
So whatever you return from make_blink() is assigned back to hello_world. That can be a function object, but it can also be something entirely different.
So when you use return decorator, you tell Python to set hello_world to the nested function object. When you use return decorator(), you tell Python to use the result of the decorator() function. Here, that's a string value. It's as if you did this:
def hello_world():
"""Original function! """
return "Hello, World!"
hello_world = "<blink>" + hello_world() + "</blink>"
And that is fine for this specific example, because body of the hello_world() function only ever returns the same string each time.
But what if you changed the original hello_world() function body to return something different each time you called it? What if you had:
import random
#make_blink
def random_greeting():
return 'Hello ' + random.choice('DonAr', 'Martijn Pieters', 'Guido van Rossum') + '!'
Now it makes a big difference what you return from the make_blink() call! For the top-level of a module, decorators are executed only once, when importing. If you used return decorator() you'd run random.choice() just once, and you have fixed the value of random_greeting to a single, static string result.
Generally speaking, decorators are expected to return a callable object again. That can be the original function (where the decorator just updates some kind of registration), a wrapper function (which does extra things before or after calling the original), or even something different entirely. But that's not set in stone anywhere, and the interpreter doesn't care either way.
Decorators are just reusable things to use in your program, a tool. If you have a specific use for a decorator that returns the result of the original function, then you are free to do so.

Python decorators with arguments

I'm having trouble understanding the concept of decorators, so basically if I understood correctly, decorators are used to extend the behavior of a function, without modifying the functions code . The basic example:
I have the decorator function, which take as parameter another function and then changes the functionality of the function given as argument:
def decorator(f):
def wrapper(*args):
return "Hello " + str(f(*args))
return wrapper
And here I have the function which I want to decorate :
#decorator
def text (txt):
'''function that returns the txt argument'''
return txt
So if I understand correctly , what actually happens "behind" is:
d=decorator(text)
d('some argument')
My question is , what happens in this case when we have three nested function in the decorator:
def my_function(argument):
def decorator(f):
def wrapper(*args):
return "Hello " +str(argument)+ str(f(*args))
return wrapper
return decorator
#my_function("Name ")
def text(txt):
return txt
Because the functionality is awesome, I can pass argument in the decorator, I do not understand what actually happens behind this call :
#my_function("Name ")
Thank you,
It is just another level of indirection, basically the code is equivalent to:
decorator = my_function("Name ")
decorated = decorator(text)
text = decorated
Without arguments, you already have the decorator, so
decorated = my_function(text)
text = decorated
my_function is used to create a closure here. The argument is local to my_function. But due to closure, when you return the decorator, the decorator function has a reference to it all the time. So when you apply decorator to text, the decorator adds extra functionality, as to be expected. It also can embed argument in its extra functionality since it has access to the environment in which it was defined.

Python decorator function called at compile time

I hope that someone familiar with Python's compilation / run-time procedures could shed some light on my question relating to how Python compiles decorator functions.
Within my sample code, I've included a testing print statement in the "writeit" decorator just before the logtofile closure is defined. If you run the entire code that I've provided, the "testing" print statement in writeit is called for each #writeit decorator defined in the Customer class-- before writeit is ever used.
Why is logtofile being called at compile time? Could someone please explain this behavior?
def writeit(func):
print('testing')
def logtofile(customer, *arg, **kwargs):
print('logtofile')
result = func(customer, *arg, **kwargs)
with open('dictlog.txt','w') as myfile:
myfile.write(func.__name__)
return result
return logtofile
class Customer(object):
def __init__(self,firstname,lastname,address,city,state,zipcode):
self._custinfo = dict(firstname=firstname,lastname=lastname,address=address,city=city,state=state,zipcode=zipcode)
#writeit
def setFirstName(self,firstname):
print('setFirstName')
self._custinfo['firstname']=firstname
#writeit
def setLastName(self,lastname):
print('setLastName')
self._custinfo['lastname']=lastname
#writeit
def setAddress(self,address):
print('setAddress')
self._custinfo['address']=address
def main():
cust1 = Customer('Joe','Shmoe','123 Washington','Washington DC','DC','12345')
cust1.setFirstName('Joseph')
cust1.setLastName('Shmoestein')
if(__name__ == '__main__'): main()
Your code runs when the module is imported. Python executes all top-level statements, including class definitions at that time.
A class definition body is executed as a function, with the local namespace becoming the class attributes. This means that class bodies are executed on import, provided the class is defined at the top-level of the module.
When Python encounters a decorated function when executing, it'll define the class, then execute the decorator function, passing in the function object and binding the return value of the decorator to the name of the function. Since the class body is executed during import, this means your decorator is executed at that time.
There is no compile time. A def statement, and the associated decorator calls are executable statements.
Accordingly, when Python loads a module, it executes the statements in order. When executing a class statement, one of the early stages is executing all of the statements in the class body. As part of that defs are run to create functions, and those function objects will be passed to decorators for processing.
Your "testing" print statement will run whenever the decorator is called, not when the function it returns is called. If you want that behaviour, move the decorator into the inner function.

Categories