Python decorator TypeError 'object is not callable' - python

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

Related

Explain how probSecond.calls equal to zero

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)

How to get return output from another script?

How can i get the output from another script?
My first script to run:
from test2 import *
class Test():
def todo (self):
mult()
addx()
if __name__ == '__main__':
Test().todo()
My second script named (test2.py):
def mult():
x= 2 * 4
print(x)
return x
def addx():
sum = x + 2
print("sum",sum)
Error:
NameError: name 'x' is not defined
In the function addx() you haven't declared x. I believe you want x from mult. So you can do something like this
def addx():
x = mult()
sum = x + 2
print("sum",sum)
You should use the return value of mult, to pass it to your second function addx as a parameter.
def todo (self):
x = mult()
addx(x)
I advise you to read the Python doc section about function : https://docs.python.org/fr/3/tutorial/controlflow.html#defining-functions
In test2.py, you have not defined x
def addx():
sum = x + 2
print("sum",sum)
The problem above is that the computer doesn't know what x is. You could pass it as a parameter:
def addx(x):
sum = x + 2
print("sum", sum)
and change your code to:
from test2 import *
class Test():
def todo(self):
addx(x=mult()) # whatever number you want
if __name__ == '__main__':
Test().todo()

Using parameters to pass values between functions

I am currently having an issue, as i am relatively new to python , it might be a very easy solution for others.
I want to pass a parameter between both functions 'eg1' and 'eg2', there is a common number the user will input (example:10) then 'eg1' will add 1 to it and 'eg2' will take the final value of 'eg1' and add 1 more to it, (example: 10 will become 11 then 12)
It is troubling me because this keeps popping up:
Traceback (most recent call last):
File "example.py", line 69, in <module>
eg2(a)
File "example.py", line 63, in eg2
b = a.d
AttributeError: 'int' object has no attribute 'd'
I can't seem to find my mistake.
class Helper:pass
a = Helper()
def one(a):
d = a
d += 1
print d
def two(a):
b = a.d
b += 1
print b
print
print ("Please enter a number.")
a = int(input('>> ')
print
one(a)
print
two(a)
Reference for parameter passing:
Python definition function parameter passing
'Print' with nothing means to leave an empty line, for me
I messed up the title, fixed.
Since you are already using a class, you can pass the number you want to increment twice as an instance attribute, and call your increment functions on that attribute. This will avoid passing the updated value after calling one in the method two
Calling one and then two makes sure that two is working on the updated value after calling one.
class Helper:
# Pass num as parameter
def __init__(self, num):
self.num = num
# Increment num
def one(self):
self.num += 1
# Increment num
def two(self):
self.num += 1
h = Helper(10)
h.one()
print(h.num) # 11
h.two()
print(h.num) # 12
Based on your comments, here's one way to get the result. I am using python3:
class Helper:
d = None
cl = Helper()
def one(a):
cl.d = a
cl.d += 1
return cl.d
def two():
cl.d += 1
return cl.d
print ("Please enter a number.")
a = int(input('>> '))
print(one(a))
print(two())

How To make decorator get invoked on a recursive function call?

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

Get inner function result without interaction of outer function in python

I want to get inner function result so i code it like
def main():
def sub():
a = 1
print a
exec main.__code__.co_consts[1]
using above code working successfully but i want to pass the argument to the sub function like...
def main():
def sub(x):
a = x + 1
return a
ans = exec main.__code__.co_consts[1]
print ans
in that problem is i don't know how to pass that x value.
that work must need to exec so that how to pass that x value with exec without interaction of main function
Maybe something like the code below, as suggested by this SO answer
def main():
def sub():
a = x + 1
print a
return a
exec(main.__code__.co_consts[1], {'x': 1} )

Categories