I'm trying to add two sets of coordinates using a class in python. This is what I have so far.
class Position:
def __init__(self, x, y):
self.x = x
self.y = y
def add(self, x):
self.x = self + x
And in a different program to run the class I have
A = Position(1, 1)
B = Position(2, 3)
A.add(B)
A.print()
So I am trying to add A and B to get (3,4). How would I do that using the add class? I don't know what to set for the parameters or what to put in the body of the function to make it work. Thanks
Convert add to be
def add(self, other):
self.x = self.x + other.x
self.y = self.y + other.y
That said, it's often useful to work with immutable objects, so why not have add return a new Position
def add(self, other):
return Position(self.x + other.x, self.y + other.y)
Then if you really want to get funky, why not override __add__()
def __add__(self, other):
return Position(self.x + other.x, self.y + other.y)
This will let you add two points together using the '+' operator.
a = Position(1, 1)
b = Position(2, 3)
c = a + b
You want something like this:
class Position(object):
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
"Add two Positions and return a new one."
return Position(self.x + other.x, self.y + other.y)
__radd__ = __add__
def __iadd__(self, other):
"In-place add += updates the current instance."
self.x += other.x
self.y += other.y
return self
def __str__(self):
"Define the textual representation of a Position"
return "Position(x=%d, y=%d)" % (self.x, self.y)
__repr__ = __str__
Now your Position class can be added using the regular Python + operator and printed using the regular print statement:
A = Position(1, 2)
B = Position(2, 3)
A += B
print(A)
Well, I'm not completely sure you actually want to change your point. If you want to change your point, I would do
class Position:
def __init__(self,x,y):
self.x = x
self.y = y
def add(self,other):
self.x += other.x
self.y += other.y
Alternatively, and more commonly (for Positions, I'd say, you'd want to get a new position)
class Position:
def __init__(self,x,y):
self.x = x
self.y = y
def __add__(self,other):
return Position(self.x + other.x, self.y + other.y)
This way, if you overrode __eq__
Position(1,2) + Position(3,4) == Position(4,6)
you may want to just import numpy and use numpy.array instead of rolling your own Position class.
Related
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.
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
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.
I'd like to be able to have the operator of my class interact with regular types in a way that I define. Lets say, for example, I have:
class Mynum(object):
def __init__(self, x):
self.x = x
def __add__(self, other):
return self.x + other.x
a = Mynum(1)
b = Mynum(2)
print a+b
This works just fine, but now if I try to do:
print a+2
I get an error since an int does not have a member named x. How do I define Mynum + int in the class? This sounds like a job for decorators or metaclasses, but I'm terribly unfamiliar with their usage. This question seems similar, but not quite identical.
def __add__(self, other):
if isinstance(other, self.__class__):
return self.x + other.x
elif isinstance(other, int):
return self.x + other
else:
raise TypeError("unsupported operand type(s) for +: '{}' and '{}'").format(self.__class__, type(other))
class Mynum(object):
def __init__(self, x):
self.x = x
def __add__(self, other):
try:
return self.x + other.x
except AttributeError:
return self.x + other
__radd__=__add__
a = Mynum(1)
b = Mynum(2)
print(a+b)
# 3
print(a+2)
# 3
print(2+a)
# 3
Why use the extra switching and/or exception handling? Using the following would be a simpler approach:
class MyNum(object):
def __init__(self, x):
self.x = x
def __add__(self, other):
return other + self.x
__radd__ = __add__
x = MyNum(5)
y = MyNum(6)
print x + 2
7
print 2 + x
7
print x + y
11
print y + x
11
Python refactoring
Both the add and sub are very similar. How does one re-factor code like this? The logic is basically inverse of each other.
class point(object):
def __init__( self, x, y ):
self.x, self.y = x, y
def add( self, p ):
x = self.x + p.x
y = self.y + p.y
return point( x, y )
def sub( self, p ):
x = self.x - p.x
y = self.y - p.y
return point( x, y )
First, standard practice is to capitalize classes (so Point, not point). I'd make use of the __add__ and __sub__ (and possibly __iadd__ and __isub__) methods, as well. A first cut might look like this:
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, p):
return Point(self.x + p.x, self.y + p.y)
def __sub__(self, p):
return Point(self.x - p.x, self.y - p.y)
I know you're looking to pull the logic out into a single method, something like:
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
def _adjust(self, x, y):
return Point(self.x + x, self.y + y)
def __add__(self, p):
return self._adjust(p.x, p.y)
def __sub__(self, p):
return self._adjust(-p.x, -p.y)
... but that seems more complicated, without much gain.
What about that:
import operator
class point(object):
def __init__( self, x, y ):
self.x, self.y = x, y
def _do_op(self, op, p):
x = op(self.x, p.x)
y = op(self.y, p.y)
return point(x, y)
def add( self, p ):
return self._do_op(operator.add, p)
def sub( self, p ):
return self._do_op(operator.sub, p)
Here's something you could do.
def __add__(self, p): # used this so that you can add using the + operator
x = self.x + p.x
y = self.y + p.y
return point(x, y)
def __sub__(self, p):
return self + point(-p.x, -p.y)