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.
Related
Asking just out of curiosity:
Intuitively, I would tend to think that the code below would fail because the __init__ function calls somefunc to populate somevar before the function was defined in the object's body, as would be the case for functions within a module.
Could you explain why this code actually works?
Thanks,
class someobj:
def __init__(self):
self.somevar = self.somefunc()
def somefunc(self):
return 'some_value'
obj = someobj()
print(obj.somevar)
Calling def assigns the function code, variables etc to its name, but doesn't run the internal code. Documentation.
The interpretater looks at this script and says
I'll define a class (basically a namespace)
Inside the class, I'll DEFINE class.init
Another define call; I'll DEFINE class.somefumc
Now the init is called by the constructor and the somefunc method is already defined.
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.
I'm a beginner at Python and I came across this issue while declaring decorators. I don't know what to call this specific scenario so I'm unable to google it effectively.
The scenario is that I declared 2 decorator functions, decorating_function1 and decorating_function2 and added them to my function named original_function. When I executed the original_function, it went into an infinite recursion. After debugging I found that the wrapper function of decorating_function2 was calling itself rather than the original_function that was passed to decorating_function2.
Furthermore, when I tried this code directly on the Python interpreter, it ran without any issues. (I'm unable to reproduce this scenario in the interpreter)
So, my question is, is there a specific scenario that can result in this type of behavior?
Code snippet of what I was trying to do. The code below runs correctly:
def decorating_function1(original_function):
print(original_function.__name__)
def wrapper(*vargs,**kwargs):
print('inside wrapper of df1')
return original_function(*vargs,**kwargs)
return wrapper
def decorating_function2(original_function):
print(original_function.__name__)
def wrapper(*vargs,**kwargs):
print('inside wrapper of df2')
return original_function(*vargs,**kwargs)
return wrapper
#decorating_function2
#decorating_function1
def original_function(name,age):
print("Name of the person is %s and his age is %d" % (name,age))
EDIT:
I haven't been able to reproduce the scenario. I was using Emacs when this issue had occurred. I've tried to reproduce this issue with other editors and the python interpreter in vain. So, I'm assuming this issue is not that major and shouldn't be possible normally.
Your code works for me fine, so I'll address the question about the calling order here.
You may have heard that "stacked" decorators are called "bottom-up". What does this mean?
When your call original_function, then decorating_function1 is called with the function as the argument. Now, this returns wrapper. Then, you have decorating_function2 "stacked" on top of decorating_function1 after this finishes.
Hence, decorating_function2 is called with an argument of wrapper. Then, this executes... so wrapper inside of decorating_function2 is executed which in turn calls decorating_function1's wrapper which then calls original_function.
So, it looks like this:
original_function (e.g. original_function(age, name) )
i) decorating_function1 -> returns "wrapper"
ii) decorating_function2(wrapper) -> returns "wrapper"
wrapper for ii) executed which is calling i)'s wrapper hence, i)
is executed and this calls original_function
If you were to add the extra bit "decorating_function1/2" before original_function.__name__ in your wrappers you would see this:
Decorating function1 original_function
Decorating function2 wrapper
inside wrapper of df2
inside wrapper of df1
Name of the person is (a name) and his age is (a age)
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)
I've been playing with my codes a little for a while, and this one is not about a bug or anything, but i just don't understand why class main() runs without needing to initialize it...
class vars():
var1 = "Universe!"
var2 = "Oscar!"
var3 = "Rainbow!"
class main():
print (vars.var1)
def __init__(self):
print (vars.var2)
print (vars.var3)
But yes, thank you very much for reading.
Unlike many other languages, class body is an executable statement in Python and is executed immediately as the interpreter reaches the class line. When you run this "program":
class Foo:
print("hey")
it just prints "hey" without any Foo object being created.
The same applies to the function definition statement def (but not to function bodies). When you run this:
def foo(arg=print("hi")):
print("not yet")
it prints "hi", but not "not yet".
When a class is created, Python executes all of the code directly inside the class declaration in a new namespace. This is so that any variables created in the class (most commonly methods, created by ordinary function declarations like def foo(self...)) are attached to the class rather than being global.
But the code still runs immediately. If it calls print() or does something else which creates a visible side effect, that will happen now, not when the class is instantiated (called to create a new instance). If you need something to happen when the class is instantiated, write an __init__() method instead.
main is a class not a function. Thus the code contained in the class declaration runs immediately because all statements are executed as they appear in code. As a method declaration is reached, it's bound to the class as a member, so in a way methods execute as well but are not called.
When Python read your code, it looked into class vars and defined all the variables. Then, it went into class main and executed the code there, as well as defining init. Python just executes whatever which is not in a function definition.