def MainCount(f):
def progFirst(*args,**kwargs):
progFirst.calls+=1
return f(*args,**kwargs)
progFirst.calls=0
return progFirst
#MainCount
def progSecond(i):
return i+1
#MainCount
def Count(i=0,j=1):
return i*j+1
print(progSecond.calls)
for n in range(5):
progSecond(n)
Count(j=0,i=1)
print(Count.calls)
Output :0
1
As per my understanding MainCount(probSecond) but I am not understant then how probSecond.calls equal to zero same in Count.calls also
As You Can See in MainCount function probFirst.Calls is attribute of function .When MainCount(probSecond) Now probSecond.calls is also attribute of MainCount function.
# A Python example to demonstrate that
# decorators can be useful attach data
# A decorator function to attach
# data to func
def attach_data(func):
func.data = 3
return func
#attach_data
def add (x, y):
return x + y
# Driver code
# This call is equivalent to attach_data()
# with add() as parameter
print(add(2, 3))
print(add.data)
Related
This question already has answers here:
How do I make function decorators and chain them together?
(20 answers)
Closed 3 months ago.
The community reviewed whether to reopen this question 3 months ago and left it closed:
Original close reason(s) were not resolved
Apologies this is a very broad question.
The code below is a fragment of something found on the web. The key thing I am interested in is the line beginning #protected - I am wondering what this does and how it does it? It appears to be checking that a valid user is logged in prior to executing the do_upload_ajax function. That looks like a really effective way to do user authentication. I don't understand the mechanics of this # function though - can someone steer me in the right direction to explain how this would be implemented in the real world? Python 3 answers please. thanks.
#bottle.route('/ajaxupload', method='POST')
#protected(check_valid_user)
def do_upload_ajax():
data = bottle.request.files.get('data')
if data.file:
size = 0
Take a good look at this enormous answer/novel. It's one of the best explanations I've come across.
The shortest explanation that I can give is that decorators wrap your function in another function that returns a function.
This code, for example:
#decorate
def foo(a):
print a
would be equivalent to this code if you remove the decorator syntax:
def bar(a):
print a
foo = decorate(bar)
Decorators sometimes take parameters, which are passed to the dynamically generated functions to alter their output.
Another term you should read up on is closure, as that is the concept that allows decorators to work.
A decorator is a function that takes a function as its only parameter and returns a function. This is helpful to “wrap” functionality with the same code over and over again.
We use #func_name to specify a decorator to be applied on another function.
Following example adds a welcome message to the string returned by fun(). Takes fun() as parameter and returns welcome().
def decorate_message(fun):
# Nested function
def addWelcome(site_name):
return "Welcome to " + fun(site_name)
# Decorator returns a function
return addWelcome
#decorate_message
def site(site_name):
return site_name;
print site("StackOverflow")
Out[0]: "Welcome to StackOverflow"
Decorators can also be useful to attach data (or add attribute) to functions.
A decorator function to attach data to func
def attach_data(func):
func.data = 3
return func
#attach_data
def add (x, y):
return x + y
print(add(2, 3))
# 5
print(add.data)
# 3
The decorator syntax:
#protected(check_valid_user)
def do_upload_ajax():
"..."
is equivalent to
def do_upload_ajax():
"..."
do_upload_ajax = protected(check_valid_user)(do_upload_ajax)
but without the need to repeat the same name three times. There is nothing more to it.
For example, here's a possible implementation of protected():
import functools
def protected(check):
def decorator(func): # it is called with a function to be decorated
#functools.wraps(func) # preserve original name, docstring, etc
def wrapper(*args, **kwargs):
check(bottle.request) # raise an exception if the check fails
return func(*args, **kwargs) # call the original function
return wrapper # this will be assigned to the decorated name
return decorator
A decorator is a function that takes another function and extends the behavior of the latter function without explicitly modifying it. Python allows "nested" functions ie (a function within another function).
Python also allows you to return functions from other functions.
Let us say, your original function was called orig_func().
def orig_func(): #definition
print("Wheee!")
orig_func() #calling
Run this file, the orig_func() gets called and prints. "wheee".
Now, let us say, we want to modify this function, to do something before this calling this function and also something after this function.
So, we can do like this, either by option 1 or by option 2
--------option 1----------
def orig_func():
print("Wheee!")
print "do something before"
orig_func()
print "do something after"
Note that we have not modified the orig_func. Instead, we have made changes outside this function.
But may be, we want to make changes in a such a way that when orig_func is called, we are able to do something before and after calling the function. So, this is what we do.
--------option 2----------
def orig_func():
print "do something before"
print("Whee!")
print "do something after"
orig_func()
We have achieved our purpose. But at what cost? We had to modify the code of orig_func. This may not always be possible, specially, when someone else has written the function. Yet we want that when this function is called, it is modified in such a way, that something before and/or after can be done. Then the decorator helps us to do this, without modifying the code of orig_func. We create a decorator and can keep the same name as before. So, that if our function is called, it is transparently modified. We go through following steps.
a. Define the decorator. In the docorator,
1) write code to do something before orig_func, if you want to.
2) call the orig_func, to do its job.
3) write code to do something after orig_func, if you want to.
b. Create the decorator
c. Call the decorator.
Here is how we do it.
=============================================================
#-------- orig_func already given ----------
def orig_func():
print("Wheee!")
#------ write decorator ------------
def my_decorator(some_function):
def my_wrapper():
print "do something before" #do something before, if you want to
some_function()
print "do something after" #do something after, if you want to
return my_wrapper
#------ create decorator and call orig func --------
orig_func = my_decorator(orig_func) #create decorator, modify functioning
orig_func() #call modified orig_func
===============================================================
Note, that now orig_func has been modified through the decorator. So, now when you call orig_func(), it will run my_wrapper, which will do three steps, as already outlined.
Thus you have modified the functioning of orig_func, without modifying the code of orig_func, that is the purpose of the decorator.
Decorator is just a function that takes another function as an argument
Simple Example:
def get_function_name_dec(func):
def wrapper(*arg):
function_returns = func(*arg) # What our function returns
return func.__name__ + ": " + function_returns
return wrapper
#get_function_name_dec
def hello_world():
return "Hi"
print(hello_world())
I'm going to use a code to response this.
What I need?: I need to modify math.sin()'s definition to add 1 always to the sine of a value
Problem: I do not have math.sin() code
Solution: Decorators
import math
def decorator_function(sin_function_to_modify):
def sin_function_modified(value):
# You can do something BEFORE math.sin() == sin_function_to_modify call
value_from_sin_function = sin_function_to_modify(value)
# You can do something AFTER math.sin() == sin_function_to_modify call
new_value = value_from_sin_function + 1;
return new_value;
return sin_function_modified
math.sin = decorator_function(math.sin);
print(math.sin(90))
Return of math.sin(90) before implement decorators: 0.8939966636005579
Return of math.sin(90) after implement decorators: 1.8939966636005579
A decorator is the function which takes another function as an argument to change its result or to give it some effect.
For example, with the code below:
# 4 + 6 = 10
def sum(num1, num2):
return num1 + num2
result = sum(4, 6)
print(result)
We can get the result below:
10
Next, we created minus_2() to subtract 2 from the result of sum() as shown below:
# (4 + 6) - 2 = 8
def minus_2(func): # Here
def core(*args, **kwargs):
result = func(*args, **kwargs)
return result - 2
return core
def sum(num1, num2):
return num1 + num2
f1 = minus_2(sum)
result = f1(4, 6)
print(result)
In short:
# ...
result = minus_2(sum)(4, 6)
print(result)
Then, we can get the result below:
8
Now, we can use minus_2() as a decorator with sum() as shown below:
# (4 + 6) - 2 = 8
def minus_2(func):
def core(*args, **kwargs):
result = func(*args, **kwargs)
return result - 2
return core
#minus_2 # Here
def sum(num1, num2):
return num1 + num2
result = sum(4, 6)
print(result)
Then, we can get the same result below:
8
Next, we created times_10() to multiply the result of minus_2() by 10 as shown below:
# ((4 + 6) - 2) x 10 = 80
def minus_2(func):
def core(*args, **kwargs):
result = func(*args, **kwargs)
return result - 2
return core
def times_10(func): # Here
def core(*args, **kwargs):
result = func(*args, **kwargs)
return result * 10
return core
def sum(num1, num2):
return num1 + num2
f1 = minus_2(sum)
f2 = times_10(f1)
result = f2(4, 6)
print(result)
In short:
# ...
result = times_10(minus_2(sum))(4, 6)
print(result)
Then, we can get the result below:
80
Now, we can use times_10() as a decorator with sum() above #minus_2 as shown below:
# ((4 + 6) - 2) x 10 = 80
def minus_2(func):
def core(*args, **kwargs):
result = func(*args, **kwargs)
return result - 2
return core
def times_10(func):
def core(*args, **kwargs):
result = func(*args, **kwargs)
return result * 10
return core
#times_10 # Here
#minus_2
def sum(num1, num2):
return num1 + num2
result = sum(4, 6)
print(result)
Then, we can get the same result below:
80
Don't forget that if a function has multiple decorators as above, they are executed from the bottom to the top as shown below:
# ((4 + 6) - 2) x 10 = 80
#times_10 # 2nd executed.
#minus_2 # 1st executed.
def sum(num1, num2):
return num1 + num2
Then, we can get the same result below as we've already seen it in the above example:
80
So, if we change the order of them as shown below:
# ((4 + 6) * 10) - 2 = 98
#minus_2 # 2nd executed.
#times_10 # 1st executed.
def sum(num1, num2):
return num1 + num2
Then, we can get the different result below:
98
Lastly, we created the code below in Django to run test() in transaction by #tran:
# "views.py"
from django.db import transaction
from django.http import HttpResponse
def tran(func): # Here
def core(request, *args, **kwargs):
with transaction.atomic():
return func(request, *args, **kwargs)
return core
#tran # Here
def test(request):
person = Person.objects.all()
print(person)
return HttpResponse("Test")
TypeError: _slow_trap_ramp() takes 1 positional argument but 2 were given
def demag_chip(self):
coil_probe_constant = float(514.5)
field_sweep = [50 * i * (-1)**(i + 1) for i in range(20, 0, -1)] #print as list
for j in field_sweep:
ramp = self._slow_trap_ramp(j)
def _set_trap_ramp(self):
set_trap_ramp = InstrumentsClass.KeysightB2962A.set_trap_ramp
return set_trap_ramp
def _slow_trap_ramp(self):
slow_trap_ramp = ExperimentsSubClasses.FraunhoferAveraging.slow_trap_ramp
return slow_trap_ramp
The error is straightforward.
ramp = self._slow_trap_ramp(j)
You are calling this method with an argument j, but the method doesn't take an argument (other than self, which is used to pass the object).
Re-define your method to accept an argument if you want to pass it one:
def _slow_trap_ramp(self, j):
It looks like your code extract contains methods of some class, whose full definition is not shown, and you are calling one method from another method (self._slow_trap_ramp(j)). When you call a method, Python automatically passes self before any other arguments. So you need to change def _slow_trap_ramp(self) to def _slow_trap_ramp(self, j).
Update in response to comment
To really help, we would need to see more of the class you are writing, and also some info on the other objects you are calling. But I am going to go out on a limb and guess that your code looks something like this:
InstrumentsClass.py
class KeysightB2962A
def __init__(self):
...
def set_trap_ramp(self):
...
ExperimentsSubClasses.py
class FraunhoferAveraging
def __init__(self):
...
def slow_trap_ramp(self, j):
...
Current version of main.py
import InstrumentsClass, ExperimentsSubClasses
class MyClass
def __init__(self)
...
def demag_chip(self):
coil_probe_constant = float(514.5)
field_sweep = [50 * i * (-1)**(i + 1) for i in range(20, 0, -1)] #print as list
for j in field_sweep:
ramp = self._slow_trap_ramp(j)
def _set_trap_ramp(self):
set_trap_ramp = InstrumentsClass.KeysightB2962A.set_trap_ramp
return set_trap_ramp
def _slow_trap_ramp(self):
slow_trap_ramp = ExperimentsSubClasses.FraunhoferAveraging.slow_trap_ramp
return slow_trap_ramp
if __name__ == "__main__":
my_obj = MyClass()
my_obj.demag_chip()
If this is the case, then these are the main problems:
Python passes self and j to MyClass._slow_trap_ramp, but you've only defined it to accept self (noted above),
you are using class methods from KeysightB2962A and FraunhoferAveraging directly instead of instantiating the class and using the instance's methods, and
you are returning references to the methods instead of calling the methods.
You can fix all of these by changing the code to look like this (see embedded comments):
New version of main.py
import InstrumentsClass, ExperimentsSubClasses
class MyClass
def __init__(self)
# create instances of the relevant classes (note parentheses at end)
self.keysight = InstrumentsClass.KeysightB2962A()
self.fraun_averaging = ExperimentsSubClasses.FraunhoferAveraging()
def demag_chip(self):
coil_probe_constant = float(514.5)
field_sweep = [50 * i * (-1)**(i + 1) for i in range(20, 0, -1)] #print as list
for j in field_sweep:
ramp = self._slow_trap_ramp(j)
def _set_trap_ramp(self):
# call instance method (note parentheses at end)
return self.keysight.set_trap_ramp()
def _slow_trap_ramp(self, j): # accept both self and j
# call instance method (note parentheses at end)
return self.fraun_averaging.slow_trap_ramp(j)
if __name__ == "__main__":
my_obj = MyClass()
my_obj.demag_chip()
I have this example code, trying to demonstrate using a callback function:
def callback(a, b):
print('Sum = {0}'.format(a+b))
def main(callback=None):
print('Add any two digits.')
if callback != None:
callback
main(callback(1, 2))
I get this result:
Sum = 3
Add any two digits.
It seems that the callback function executes before the logic in main. Why? How can I make it so that the callback is not called until it is used within main?
See also: Python Argument Binders
In this code
if callback != None:
callback
callback on its own doesn't do anything; it accepts parameters - def callback(a, b):
The fact that you did callback(1, 2) first will call that function, thereby printing Sum = 3, and then main() gets called with the result of the callback function, which is printing the second line
Since callback returns no explicit value, it is returned as None.
Thus, your code is equivalent to
callback(1, 2)
main()
Solution
You could try not calling the function at first and just passing its handle.
def callback(n):
print("Sum = {}".format(n))
def main(a, b, _callback = None):
print("adding {} + {}".format(a, b))
if _callback:
_callback(a+b)
main(1, 2, callback)
Here's what you wanted to do :
def callback(a, b):
print('Sum = {0}'.format(a+b))
def main(a,b,f=None):
print('Add any two digits.')
if f is not None:
f(a,b)
main(1, 2, callback)
The problem is that you're evaluating the callback before you pass it as a callable. One flexible way to solve the problem would be this:
def callback1(a, b):
print('Sum = {0}'.format(a+b))
def callback2(a):
print('Square = {0}'.format(a**2))
def callback3():
print('Hello, world!')
def main(callback=None, cargs=()):
print('Calling callback.')
if callback is not None:
callback(*cargs)
main(callback1, cargs=(1, 2))
main(callback2, cargs=(2,))
main(callback3)
Optionally you may want to include a way to support keyword arguments.
As mentioned in the comments, your callback is called whenever it's suffixed with open and close parens; thus it's called when you pass it.
You might want to use a lambda and pass in the values.
#!/usr/bin/env python3
def main(callback=None, x=None, y=None):
print('Add any two digits.')
if callback != None and x != None and y != None:
print("Result of callback is {0}".format(callback(x,y)))
else:
print("Missing values...")
if __name__ == "__main__":
main(lambda x, y: x+y, 1, 2)
Your code is executed as follows:
main(callback(1, 2))
callback function is called with (1, 2) and it returns None (Without return statement, your function prints Sum = 3 and returns None)
main function is called with None as argument (So callback != None will always be False)
This is an old post, but perhaps the following may be additional clarification on writing and using a callback function, especially if you wonder where it gets its arguments from and whether you can access its return values (if there is no way to get it from the function that takes the callback function).
The following code defines a class CallBack that has two callback methods (functions) my_callback_sum and my_callback_multiply. The callback methods are fed into the method foo.
# understanding callback
class CallBack:
#classmethod
def my_callback_sum(cls, c_value1, c_value2):
value = c_value1 + c_value2
print(f'in my_callback_sum --> {c_value1} + {c_value2} = {value}')
cls.operator = '+'
return cls.operator, value
#classmethod
def my_callback_multiply(cls, c_value1, c_value2):
value = c_value1 * c_value2
print(f'in my_callback_multiply --> {c_value1} * {c_value2} = {value}')
cls.operator = '*'
return cls.operator, value
#staticmethod
def foo(foo_value, callback):
_, value = callback(10, foo_value)
# note foo only returns the value not the operator from callback!
return value
if __name__ == '__main__':
cb = CallBack()
value = cb.foo(20, cb.my_callback_sum)
print(f'in main --> {value} and the operator is {cb.operator}')
value = cb.foo(20, cb.my_callback_multiply)
print(f'in main --> {value} and the operator is {cb.operator}')
result:
in my_callback_sum --> 10 + 20 = 30
in main --> 30 and the operator is +
in my_callback_multiply --> 10 * 20 = 200
in main --> 200 and the operator is *
As you can see one value for the callback function c_value2 it gets from argument foo_value in foo and given in main the value 20, while c_value1 it gets internally from foo in this case the value 10 (and may be not clearly visible if foo is some method of a third party imported module, like pyaudio).
The return value of the callback function functions can be retrieved by adding it to the namespace of the class CallBack, in this case cls.operator
You can use anonymous functions
def callback(a, b):
print('Sum = {0}'.format(a+b))
def main(callback=None):
print('Add any two digits.')
if callback is not None:
callback()
tmp_func = lambda: main(lambda: callback(2,3))
tmp_func()
#OR
tmp_func = lambda x,y: main(lambda: callback(x,y))
tmp_func(2,4)
So here's an extension to this question: https://stackoverflow.com/a/37568895/2290820
on how to optionally Enable or Disable Decorator on a Function.
On those lines, I came up with something like this to make decorator get invoked on a recursive call:
def deco(f):
def fattr(attr):
f.attr = attr
def closure(*args):
f(*args)
f.unwrap = f
f.closure = closure
return f
return fattr
#deco
def printa(x):
if x > 1:
print x
return printa(x-1)
else:
print x
return
printa({1:1})(5)
# do the same call w/o deocorator
def finta(x):
if x > 1:
print x
return finta(x-1)
else:
print x
return
finta(5) # this works
to experiment with decorators on a recursive function. Clearly, printa recursive version is not behaving the way it should be.
I could do
g = printa({1:1})
g.closure(5)
to turn on the decorator option or not use that option. Anyway, regardless of good or bad design, How can I make decorator get invoked on a recursive call?
In your deco you have an assignment f.attr = attr that "eats" your argument after first recursive call. Your should modify your recursive call this way:
def deco(f):
def fattr(attr):
f.attr = attr
def closure(*args):
f(*args)
f.unwrap = f
f.closure = closure
return f
return fattr
#deco
def printa(x):
if x > 1:
print x
return printa(None)(x-1) # None will be assigned to f.attr
else:
print x
return
printa({1:1})(5)
5
4
3
2
1
I am trying to get myself familiar with decorators.
This is a program I created to do so, but it keeps giving me an TypeError: 'int' object is not callable error, which I don't know how to fix.
#Filename: decorator_practice.py
def add(x):
def add_1():
add_1 = x() + 1
return add_1
def minus(x):
def minus_1():
return x() - 1
return minus_1
def multi(x, times=2):
def multi_2():
return x() * 2
def multi_3():
return x() * 3
def multi_4():
return x() * 4
if times == 2:
return multi_2
elif times == 3:
return multi_3
elif times == 4:
return multi_4
else:
return "Please enter times between 2 and 4"
def create_x():
x = input('Give variable x a value: ')
return x
add(create_x()())
I run this and type: 5
Can anyone help me? Thanks!
Your create_x function returns an integer:
def create_x():
x = input('Give variable x a value: ')
return x
so create_x()() is never going to work.
Part of the problem is that you've used poor parameter names, which is confusing you - you have two xs which refer to two completely different things. Using your add decorator as an example, modify to:
def add(func):
def add_1():
return func() + 1 # you should return from the inner function
return add_1
Now hopefully it is clear that the argument to add should be a function, which is called inside add_1. Therefore you could do:
adder = add(create_x) # don't call create_x yet!
adder() # calling add_1, which calls create_x
which simplifies to:
add(create_x)() # note ordering of parentheses
Note that this could also be written:
#add
def create_x():
...
create_x()
where the syntax #add means create_x = add(create_x).
Once you've mastered simple decorators, note that your multi will not work as you expect - see e.g. python decorators with parameters for creating decorators that take arguments.
You have unnecessary (), change add(create_x()()) to add(create_x()),
and I suggest using x = int(raw_input('Give variable x a value: '))
See the following example:
def add(x):
def add_1():
#add_1 = x() + 1 # remove this line
return x+1
return add_1
def create_x():
x = input('Give variable x a value: ')
return x
b = add(create_x())
print 'answer: ', b()
localhost# python t.py
Give variable x a value: 5
answer: 6