Missing 2 required positional arguments - Classmethod Python - python

Sorry, I'm struggling at this for quite some time. I'm trying to use function totalPayments which uses the monthlyPayment class function with parameters pass through in the initialisation phase. I'm getting an error missing 2 required positional arguments
class Loan(object):
def __init__(self, asset, face, rate , term):
self._asset = asset
self._face = face
self._rate = rate
self._term = term
#classmethod
def monthlyPayment(cls,face,rate,term,period=None):
return ((rate*face*((1+rate)**term)))/(((1+rate)**term)-1)
def totalPayments(self):
return (self.monthlyPayment(self) * self._term)
l = Loan(None,1000,0.025,10)
print(l.totalPayments()) # gets an error missing 2 required positional arguments
edit:
Thank you very much for the hekp and I should be amending my def monthlyPayment function to take in the arguments

You are calling monthlyPayment from the instance (self), and you're not providing arguments for face, rate, and term.
It also shouldn't be a classmethod, since you use attributes of the instance:
class Loan(object):
def __init__(self, asset, face, rate , term):
self._asset = asset
self._face = face
self._rate = rate
self._term = term
def monthlyPayment(self, period=None):
return ((self._rate*self._face*((1+self._rate)**self._term)))/(((1+self._rate)**self._term)-1)
def totalPayments(self):
return (self.monthlyPayment() * self._term)

The stack error you get is:
Traceback (most recent call last):
File "C:/Users/cd00119621/PycharmProjects/ideas/stackoverflow.py", line 16, in <module>
print(l.totalPayments())
File "C:/Users/cd00119621/PycharmProjects/ideas/stackoverflow.py", line 13, in totalPayments
return (self.monthlyPayment(self) * self._term)
TypeError: monthlyPayment() missing 2 required positional arguments: 'rate' and 'term'
The clue here is that its the monthlyPayment() method thats giving the error missing 2 args. this method expects 3 args passed to it (excluding self) and the 4th is optional.
def monthlyPayment(cls,face,rate,term,period=None):
but when you call this from your totalPayments method you only pass one argument which is self.
return (self.monthlyPayment(self) * self._term)
you dont need to pass self, it will be passed automatically, so you need to pass the other 3 expected params face,rate,term

Related

Python dynamic function & parameters call - str object is not callable

I´m trying to come up with a dynamic function calling system. I have a database with a bunch of differents levels:
Decision Evaluator > Function (response curve) parameters > Inputs.
Choosing a Decision Evaluator may call 10 different functions but only 5 inputs, treated differently through the parameters. So it would be way easier to have a dynamic system rather than create all the sub-calls for each main level.
In the test below, I can dynamically call a lower-level function from an upper level ('test'). When I try to pass arguments, I get the error 'str' object is not callable. Here's the trace:
C:\ProgramData\Anaconda3\lib\site-packages\openpyxl\worksheet\_reader.py:312: UserWarning: Data Validation extension is not supported and will be removed
warn(msg)
Traceback (most recent call last):
File "C:\Users\*\considerations.py", line 28, in <module>
ich.dynamic_call(abcd_3(show_test))
TypeError: 'str' object is not callable
init ICH...
oouh weee look at me
Process finished with exit code 1
considerations.py:
from input_clearing_house import InputClearingHouse
import pandas as pd
inputs = pd.read_excel(r'AXIS_DB.xlsx', sheet_name='Inputs')
considerations = pd.read_excel(r'AXIS_DB.xlsx', sheet_name='Considerations')
decision_score_evaluator = pd.read_excel(r'AXIS_DB.xlsx', sheet_name='DecisionScoreEvaluator')
decision_maker = pd.read_excel(r'AXIS_DB.xlsx', sheet_name='DecisionMaker')
considerations = pd.merge(considerations, inputs, on='input_name')
# print(considerations)
ich = InputClearingHouse()
abcd_2 = 'test'
abcd_3 = 'multi21'
show_test = 'dynamite'
ich.dynamic_call(abcd_2)
ich.dynamic_call(abcd_3(show_test))
input_clearing_house.py:
import math
class InputClearingHouse:
def __init__(self):
print('init ICH...')
def dynamic_call(self, name, *args, **kwargs):
call_fct = f'{name}'
if hasattr(self, call_fct) and callable(func := getattr(self, call_fct)):
func(*args, **kwargs)
def test(self):
print("oouh weee look at me")
def multi21(self, *args):
for arg in args:
print(arg)
def distance_to_target(self, source: tuple, target: tuple) -> float:
return math.sqrt((source[0] - target[0]) ** 2 + (source[1] - target[1]) ** 2)
def my_endurance(self, current: int, maximum: int) -> float:
return current / maximum
abcd_3(show_test) is trying to use abcd_3 as a function, but it's a string that names a function.
ich.dynamic_call() expects the name and arguments of the function to call to be separate arguments, so you should use
ich.dynamic_call(abcd_3, show_test)
Your dynamic_call() method already copes with variable numbers of arguments.
I think you just meant to add arguments:
ich.dynamic_call(abcd_3, show_test)

TypeError: read_csv() takes from 0 to 1 positional arguments but 2 were given

What am I missing here? I have tried looking at the code but I do not know where the extra positional argument is located at,
def read_csv(path: str = None) -> List[List] :
lead = Path(__file__).parent / f'../data/{path}'
entries = []
print('Reading dataset...')
with open(lead, 'r') as csvfile:
video_reader = csv.reader(csvfile)
for row in video_reader:
entries.append(row)
return print(entries)
Traceback (most recent call last):
File "C:/Users/MEDIAMARKT/Desktop/booking/__main__.py", line 15, in <module>
gui = GUI()
File "C:\Users\MEDIAMARKT\Desktop\booking\gui.py", line 22, in init
self.upload_data()
File "C:\Users\MEDIAMARKT\Desktop\booking\gui.py", line 84, in upload_data
self.booking.read_csv(path)
TypeError: read_csv() takes from 0 to 1 positional arguments but 2 were given
Your error is elsewhere, not in the snippet provided, since as a standalone function, that code should work fine.
Looking at your traceback, you've introduced classes, so reading your error
2 were given
When you call a class function, the instance of that class is always supplied as a parameter
example
class Foo:
def bar(self, other=None): # self is a required argument for instance methods
pass
xyz = 'something'
booking = Foo()
booking.bar() # 1 parameter provided - the instance itself
booking.bar(xyz) # 2 parameters provided - the instance and the string
So, to fix your function, you need to add the self parameter, even if you don't plan on using it.
Before, the path variable you used wasn't actually a string, so the type checker should have been throwing an error as well
class Booking():
def read_csv(self, path:str = None) -> List[List]:
# TODO
return []

method() takes 1 positional argument, but 4 were given?

So this is my code, that uses recursion to solve the Tower of Hanoi, and this error comes up whenever I try to run solve(). The other function works fine (I've tested it), and all of my methods contain self. I haven't found any similar error on SO, that don't have to do with someone forgetting self. So, why's this going wrong?
class RODS():
pass
class HANOI():
def __init__(self,rings,start,end):
self.rings=rings
self.start=start
self.end=end
self.rods=RODS()
for i in range(rings):
setattr(self.rods,"rod"+str(i+1),[])
self.rods.rod1=[1,2,3]
def solve(self):
if self.rings == 1:self.pm(self.start,self.end)
else:
other=6-(self.start+self.end)
self.solve(self.rings-1,self.start,other)
self.pm(self.start,self.end)
self.solve(self.rings-1,other,self.end)
def pm(self,start,end):
rod=getattr(self.rods,"rod"+str(start+1))
ring=rod[0]
end_rod=getattr(self.rods,"rod"+str(end+1))
end_rod.append(ring)
rod.remove(ring)
print("Ring:",ring,"-> Rod:",end)
hanoi=HANOI(3,1,3)
hanoi.solve()
This is the error:
Traceback (most recent call last):
File "main.py", line 35, in <module>
hanoi.solve()
File "main.py", line 20, in solve
self.solve(self.rings-1,self.start,other)
TypeError: solve() takes 1 positional argument but 4 were given
You need parameters for solve, but you probably are OK with default values for the top-level call:
def solve(self, start=1, stop=3, other=2):
if self.rings == 1:
self.pm(self.start, self.end)
else:
other = 6 - (self.start + self.end)
self.solve(self.rings-1, self.start, other)
self.pm(self.start, self.end)
self.solve(self.rings-1, other, self.end)
Because your method is not receiving any arguments and your are calling it again with 3 arguments and the method only expect the argument self.
def solve(self):
else:
self.solve(self.rings-1,self.start,other) # 3 arguments + self argument = 4 arguments

Using decorator in a class in python

For understanding decorators in Python, i created in a class an example. But when i run it i receive an error.
class Operation:
def __init__(self, groupe):
self.__groupe = groupe
#property
def groupe(self):
return self.__groupe
#groupe.setter
def groupe(self, value):
self.__groupe = value
def addition(self, func_goodbye):
ln_house = len('house')
ln_school = len('school')
add = ln_house + ln_school
print('The result is :' + str(add))
return func_goodbye
#addition
def goodbye(self):
print('Goodbye people !!')
if __name__ == '__main__':
p1 = Operation('Student')
p1.goodbye()
I receive this error :
Traceback (most recent call last):
File "Operation.py", line 1, in
class Operation:
File "Operation.py", line 21, in Operation
#addition
TypeError: addition() missing 1 required positional argument: 'func_goodbye'
You can have a class scoped decorator, however there won't be a self when the decorator is called
a decorator:
#foo
def bar(): ...
is roughly equivalent to
def bar(): ...
bar = foo(bar)
in your particular example, if you remove the self parameter, it should function as you expect:
def addition(func_goodbye):
ln_house = len('house')
ln_school = len('school')
add = ln_house + ln_school
print('The result is :' + str(add))
return func_goodbye
#addition
def goodbye(self):
print('Goodbye people !!')
for good measure, I might del addition after that just to ensure it isn't accidentally called later
(an aside: one unfortunate side-effect of this is many linters and type checkers will consider this "odd" so I've yet to find a way to appease them (for example mypy))

not enough arguments passed to __init__()

What is the error below? Also, is there a better way to implement the following classes?
#!/usr/bin/python
class Datacenters:
def __init__(self,name,location,cpu,mem):
self.name=name
self.location=location
self.cpu=cpu
self.mem=mem
def getparam(self):
return self.name,self.location ,self.cpu,self.mem
def getname(self):
return self.name
class WS(Datacenters):
def __init__(self,name,location,cpu,mem,obj):
#datacentername = Datacenters.__init__(self) #To which data center it is associated
self.dcname =obj.name #To which data center it is associated
Datacenters.__init__(obj,name,location,cpu,mem)
def getparam(self,obj):
self.name,self.location ,self.cpu,self.mem = obj.getparam()
print self.dcname
#return self.name,self.location ,self.cpu,self.mem,obj.name
def getwsname(self):
return self.name
class Pcs(WS):
def __init__(self,name,location,cpu,mem,obj):
self.wsname = obj.getwsname() #To which WS it is associated
WS.__init__(obj,name,location,cpu,mem)
def getparam(self,obj):
print obj.getparam()
print self.wsname
a = Datacenters("dc1","Bl1",20,30)
print a.getparam()
b = WS("WS1","Bl1",21,31,a)
print b.getparam(a)
c = Pcs("PC1","Bl1",20,30,b)
#print c.getparam(b)
output:
Press ENTER or type command to continue
('dc1', 'Bl1', 20, 30)
dc1
None
Traceback (most recent call last):
File "class1.py", line 45, in <module>
c = Pcs("PC1","Bl1",20,30,b)
File "class1.py", line 34, in __init__
WS.__init__(obj,name,location,cpu,mem)
TypeError: __init__() takes exactly 6 arguments (5 given)
The error is that you pass in five arguments, but the __init__ needs six. Count them:
def __init__(self,name,location,cpu,mem,obj):
Six arguments. You call it like so:
WS.__init__(obj,name,location,cpu,mem)
Five arguments. The first one, self is missing. What you should ask yourself is why you don't have to pass in six arguments all the time.
And that is because self is passed in automatically when you call the method on an instance. However, in this case you don't call it on an instance, you call it directly on the class. There is of course no need to do so in this case, the correct syntax is:
WS(obj,name,location,cpu,mem)
As you indeed above note works further up.

Categories