Function missing 1 required positional argument [duplicate] - python

This question already has an answer here:
Missing 1 required positional argument
(1 answer)
Closed last year.
I'm getting this error :
Traceback (most recent call last):
File "C:/Users/mali03/Desktop/Python/Practice/p2.py", line 18, in <module>
first.subtraction(1, 2)
TypeError: subtraction() missing 1 required positional argument: 'y'
Here is my calculator class
class calculator:
def __init__(self, x, y):
self.x = x
self.y = y
def addition(self, x, y):
return self.x + self.y
def subtraction(self, x, y):
if self.x > self.y:
return self.y - self.x
else:
return self.x - self.y
I then call subtraction with the following:
first = calculator
first.subtraction(1, 2)

Like stated previously, you don't have to include parameters in your addition or subtraction functions if you already gather that information in the __init__ function.
Like so:
class calculator:
def __init__(self, x, y):
self.x = x
self.y = y
def addition(self):
return self.x + self.y
def subtraction(self):
if self.x > self.y:
return self.y - self.x
else:
return self.x - self.y
first = calculator
print(first(5,10).addition())
Alternatively, if you do want to have x and y parameters in your addition and subtraction functions, you can adjust your code like so:
class calculator:
def addition(self, x, y):
return x + y
def subtraction(self, x, y):
if x > y:
return y - x
else:
return x - y
first = calculator
print(first().addition(5, 10))
Where parameters of individual functions are used instead to the parameters given to the class object.
Either ways work, it depends on how you want to use the class.

Alternatively you could do:
class calculator():
def addition(self, x, y):
return x + y
def subtraction(self, x, y):
if x > y:
return y - x
else:
return x - y
first = calculator()
print(first.subtraction(1, 2))
Also not entirely sure if x > y: was your intention or if you really wanted if x < y:

You don't need to specify x and y in subtraction or addition:
class calculator:
def __init__(self, x, y):
self.x = x
self.y = y
def addition(self):
return self.x + self.y
def subtraction(self):
if self.x > self.y:
return self.y - self.x
else:
return self.x - self.y
self will cover retrieving x and y for you, since you are referencing those instance variables. Otherwise, you will need to specify them on call:
# Yields 2-1 rather than 4-3
result = calculator(1,2).subtraction(3,4)
You do, however, need to specify them when instantiating your class
myinst = calculator(1,2)

first = calculator makes first refer to the class. But first = calculator(1, 2) makes first an object of the class calculator. This initializes self for all other functions called on first. This also sets the values for self.x and self.y because __init__ is called as soon as object is created. Hence, when first = calculator(x, y) is used, self has a value along with self.x and self.y, and when parentheses are not used, they do not have a value. That gives a missing argument error.
Next, as others have already referred, once __init__ is called, x and y are initialized for the object. And so, you don't need them while declaring other functions. self.x and self.y can directly be used there which will now refer to 1 and 2 respectively in this case.
Hope it helps.

Related

How do I only inherit some variables from a super class in Python

I am trying to make a subclass, Square, from a superclass, Shape.
class Shape :
def __init__ (self, x, y) :
self.x = x
self.y = y
self.description = "This shape has not been described yet"
def area (self) :
return self.x * self.y
def describe (self, text) :
self.description = text
I have tried
class Square (Shape) :
def __init__ (self, x) :
self.x = x
self.y = x
self.description = "This shape has not been described yet"
which seems to work, but the only thing that actually changes in Square is self.y = x, so I wonder if I could do the same thing without having to write self.x and self.description again.
(I tried doing something like this:
class Square (Shape) :
def __init__ (self, x) :
self.y = x
super().__init__()
but, when I create a Square object, a type error occurs:
TypeError: init() missing 2 required positional arguments: 'x' and 'y')
A Square is a Shape whose x and y are the same. Hence:
class Square(Shape):
def __init__(self, x):
super().__init__(x, x)
You just need to call Shape.__init__(self, x, y) with your x as both the x and y parameters.
Just call the super function inside __init__. Put both the arguments equal to x.
class Square(Shape):
def __init__(self, x):
super().__init__(x, x)

Mock a Python class __init__ partially?

I have a Python class with complicated initialization. I would like to mock the class initialization to avoid writing too much scaffolding code. I want to test its non-mocked method.
A simple example:
class Person:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def do_work(self):
return self.x + self.y
There's an answer which shows how to get it done and it works - https://stackoverflow.com/a/21771920/3346915.
Here's a passing test:
from unittest.mock import patch
with patch.object(Person, '__init__', lambda self: None):
person = Person()
person.x = 3
person.y = 4
assert person.do_work() == 7
I wonder, however, if it would be possible to pass x and y as part of the Person initialization to avoid assigning the fields after the construction to reduce the amount of code?
I wonder if this would be possible?
from unittest.mock import patch
with patch.object(Person, '__init__', lambda self, x, y: None):
person = Person(x=3, y=4)
assert person.do_work() == 7
This doesn't work of course because the x and y values are not assigned to the person instance.
lambdas do not support assignment, but you do not have to use lambda as third argument - normal (named) function will work too, so you can do:
class Person:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def do_work(self):
return self.x + self.y
from unittest.mock import patch
def newinit(self, x, y):
self.x = x
self.y = y
with patch.object(Person, '__init__', newinit):
person = Person(x=3, y=4)
assert person.do_work() == 7
(tested in Python 3.7.3)

Python giving me two different results while performing the same operation on the same objects twice

I created a class vector2D in python with a method to add vectors. Then I used it to add the same vectors twice and got different results. Why did that happen?
Here's the code:
class vector2D:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
self.x += other.x
self.y += other.y
return self.x, self.y
#Creating vector objects
v1 = vector2D(2, 3)
v2 = vector2D(4, 8)
#using the redefined addition operator to add vector objects
v = v1 + v2 #output: (6, 11)
print(v)
#Adding again
v = v1 + v2 #output: (10, 19)
print(v)
You both add the vectors in place and return the result!
def __add__(self, other):
self.x += other.x
self.y += other.y
return self.x, self.y
This changes first vector's parameters! += means self.x = self.x + other.x.
Do this instead:
def __add__(self, other):
result_x = self.x + other.x
result_y = self.y + other.y
return result_x, result_y
Your doing in place assignment, when you do this
self.x += other.x
you are changing the x attribute of the object it self, so when you do the second addition the x is changed.
One more thing __add__ should return an instance of the same class, Developer when using your class they will expect when they add vector2d to another vector2d they get a vector2d but you are returning a tuple:
class vector2D:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return self.__class__(self.x + other.x, self.y + other.y)
So when you add vector2D + vector2D you get vector2D instance.

Python program not working..The main part keep showing error

class point:
def __init__(self,z,d):
self.x = z
self.y = d
def display(self,z,d):
self.x = self.z
self.y = self.d
def setX(self, z):
self.x = z
def setY(self, d):
self.y = d
def getX(self):
return self.x
def getY(self):
return self.y
def show(self):
print(self.x)
print(self.y)
p1 = point() //error
print("Point P1:")
p1.show()
print("Updated value:")
p1.display(5, 6)
p1.setX(9)
p1.setY(4)
p1.show()
print("Point P2:")
p2=point()
p2.setX(9)
p2.setY(4)
p2.show()
print("Updated value:")
p2.display(6, 3)
p2.show()
My program keep showing me error that z and d are missing in the object section,,i donno how to correct it i keep trying but more n more errors keeps showing up.
Traceback (most recent call last):
File "P:\xxxyyy.py", line 29, in <module>
p1 = point() //error
TypeError: __init__() missing 2 required positional arguments: 'z' and 'd'
Don't forget to pass in z and d in the constructor, eg:
p1 = point(1,2)
Also, in the display function, you try to set self.x to self.z and self.y to self.d. self.z and self.d don't exist (self means it should be a class attribute, which it isn't), you should instead use the function's input parameters:
self.x = z
self.y = d
class point:
def __init__(self,z,d):
self.x = z
self.y = d
def display(self,z,d):
self.x = z #not self.z
self.y = d #not self.d
def setX(self, z):
self.x = z
def setY(self, d):
self.y = d
def getX(self):
return self.x
def getY(self):
return self.y
def show(self):
print(self.x)
print(self.y)
First fix this, you are updating with display using two new variables that its taking in, so we just cast those variables not self.z / self.d
p1 = point(1,2)
print("Point P1:")
p1.show()
Create your instance with values that it needs __ini__(self, z, d) needs a z and d value
print("Updated value:")
p1.display(5, 6)
p1.setX(9)
p1.setY(4)
p1.show()
If p1.display is updating the values to 5,6 then why update them again with setX/setY pretty much you are making z=5, d=6 then z=9 d=4
And then you just repeat these small errors for p2

python local variables vs self

What's the difference between self.x+self.y and x+y in the code below?
class m2:
x, y = 4, 5
def add(self, x, y):
return self.x + self.y
def add2(self, x, y):
return x + y
>>> x = m2()
>>> print "x.add(self.x + self.y = )", x.add(1, 2)
x.add(self.x + self.y = ) 9
>>> print "x.add2(x + y = )", x.add2(1, 2)
x.add2(x + y = ) 3
Why does self.x + self.y return 9 vs x + y returns 3?
In add you are calling the class variables and ignoring the method arguments x and y.
class m2:
# these variables are class variables and are accessed via self.x and self.y
x, y = 4, 5
def add(self, x, y):
return self.x + self.y # refers to 4 and 5
def add2(self, x, y):
return x + y # refers to input arguments x and y, in your case 1 and 2
When defining x and y in the class scope it makes them class variables. They are part of the the class m2 and you don't even need to create an instance of m2 to access them.
print m2.x, m2.y
>> 4, 5
However, you are also able to access them via an instance as if they were instance variables like this:
m = m2()
print m.x, m.y
>> 4, 5
The reason behind this is that the interpreter will look for instance variables with names self.x and self.y, and if they are not found it will default to class variables.
Read more about class attributes in the python documentation.
The difference is that when you use self you refer to the member of the instance of your class
When you use X and Y dirrectly you refer to the parameter that you use in your function
This is a simplification of your class
class m2:
x_member1, y_member2 = 4, 5
def add(self, x_parameter1, y_parameter2 ):
return self.x_member1+ self.y_member2
def add2(self, x_parameter1, y_parameter2 ):
return x_parameter1 + y_parameter2
When a class method is called, the first argument (named self by convention) is set to the class instance. When the method accesses attributes of self, it is accessing those attributes in the class instance, and their values persist in that instance.
On the other hand, if a class method accesses bare variables, those variables are strictly local to those methods and their values do not persist across calls to class methods of that instance.
class m2:
x, y = 4, 5 #This are class attributes
def add(self, x, y ):
return self.x + self.y # This are instance variables
def add2(self, x, y ):
return x + y # This are local variables
Class variables are common to each instance of the class. Instance variables are only avaible to that instance. And local variables are only avaible in the scope of the function.
In add, when you do self.x it's refering to the class variable x cause it's also part of the instance. In add2 it's refering to local variables
The same results could be achieved if those methods were class methods or static methods (With proper adjustments)
Class method:
class m2:
x, y = 4, 5
#classmethod
def add(cls, x, y):
return cls.c + cls.y #Here you're calling class attributes
#classmethod
def add2(cls, x, y):
return x + y
Results:
>>> m.add(1,2)
9
>>> m.add2(1,2)
3
Static method:
class m2:
x, y = 4, 5
#staticmethod
def add(x, y):
return m2.c + m2.y #Here you need to call the class attributes through the class name
#staticmethod
def add2(x, y):
return x + y
Results:
>>> m2.add(1,2)
9
>>> m2.add2(1,2)
3
x and y will be local by default. The self.x and self.y are persisted in that instance, x and y will only be there locally.
class Dog():
def __init__(self):
x = "local"
self.y = "instance"
d = Dog()
print(d.y)
#=> instance
print(d.x)
#=> AttributeError: Dog instance has no attribute 'y'

Categories

Resources