Vector multiplication python - python

Hello im learning python and i get class topic.
I recived a error message like this:
"TypeError: __init__() missing 1 required positional argument: 'y'"
this is my code from shell:
class Vektor():
""" Bu bir vektör sınıfıdır"""
def __init__(self,x,y):
self.x = x
self.y = y
def boyu(self):
boy = (self.x**2+self.y**2)**0.5
return boy
def __repr__(self):
return ("%di + %dy" %(self.x, self.y))
def __sub__(self,digeri):
return Vektor(self.x - digeri.x, self.y - digeri.y)
def __add__(self,digeri):
return Vektor(self.x + digeri.x, self.y + digeri.y)
def __eq__(self,digeri):
if self.boyu() == digeri.boyu(): return True
def __mul__(self,digeri):
self.x = Vektor(self.x + digeri.x)
self.y = Vektor(self.y + digeri.y)
return Vektor(self.x*digeri.x,self.y*digeri.y)
When i try to create a C = A*B like this i get error:
TypeError: init() missing 1 required positional argument: 'y'
Im already thank you and i want to remind im a newbite in programming :))

How many arguments does Vektor.__init__ require? Ignoring self, it's two - x and y.
When you wrote return Vektor(self.x*digeri.x,self.y*digeri.y), you passed two arguments, so this works.
When you wrote self.x = Vektor(self.x + digeri.x), this doesn't work, because you don't pass a second argument for the y value.
When Python gave you the error, it should have included a line number, which is supposed to show where the error occurred. You didn't include that, but it was this line, wasn't it?
Since Vektor is supposed to contain two scalars and not sometimes replace them with two vectors, you could just write
self.x = self.x + digeri.x # still not a vector
self.y = self.y + digeri.y # also not a vector
but the more important lesson is to read the error message carefully. Everything you needed was there.
A note on operator semantics: since you wouldn't normally expect an expression like x = v * w to modify x, you shouldn't be mutating self inside the operator function anyway.
You return the resultant vector, which is enough. I showed you how to fix the syntax of those two lines, but you should really just remove them entirely.
And another note on vectors: overloading * isn't such an obvious win as it is for a scalar numeric type, because vectors usually have more than one possible type of product.

In __mul__ you do for some reason:
self.x = Vektor(self.x + digeri.x)
which is calling Vektor.__init__ providing only the positional argument x, with the value self.x + digeri.x, but nothing for y, thus the error.
Also this attempts to change the attribute x into an object from Vektor itself, I can't imagine that this is somehow what you want.
To me it is not clear what the 2 lines before the return statement in your __mul__ are supposed to do. Also both lines will produce the error you see.
Should your __mul__ be the dot product? If so, try:
return self.x*digeri.x + self.y*digeri.y
Another simplification to your class could be to allow iteration on your coords, like:
#property
def coords(self):
return self.x, self.y
def __iter__(self):
return self.coords.__iter__()
Then your dot product might just look like:
def dot(self, w):
"""
The dot product of self and other vector w.
"""
return sum([xi_s * xi_w for xi_s, xi_w in zip(self, w)])
There is VecPy, a very simple example class that does this kind of things. Maybe having a look can give you some more ideas.

The error is due to
self.x = Vektor(self.x + digeri.x)
When we call Vector like the way you write the syntax, it is thinking that you want to initialize it and it is expecting two inputs. Just get rid of the first two lines of mul function should fix the problem.

Related

How to repeat string without a function

I found a task where I am asked to implement some object that repeats a string n times but condition is that this something must not be a function. I have tried the following:
class str_repeat:
def __init__(self,x,y):
self.s = x * y
def __repr__(self):
return self.s
but this did not work.Some Hints would help a lot
Humm! str_repeat must be a callable.
What do you think of:
str_repeat = str.__mul__

Python thinks I'm passing 3 arguments although I'm only passing 2

I've written a basic Vector class for dealing with vectors. Calculating their magnitude and whatnot. I have two overloaded constructors one taking two arguments x and y and one taking a tuple (x,y).
When I initialize a variable it gives me the error:
TypeError: __init__() takes 2 positional arguments but 3 were given.
What am I missing?
class Vector:
x = 0.0
y = 0.0
def __init__(self, x, y):
self.x = x
self.y = y
def __init__(self, coordinates):
self.x = coordinates[0]
self.y = coordinates[1]
v1 = Vector(1,3)
print(v1.x)
Python doesn't support overloading, so you overwrite the first __init__ method with the second one. The second one takes only 1 argument: coordinates. That Python writes 3 arguments is because the instance (self) is passed implicitly.
Remove the second __init__ method and it will work correctly.
If you like multiple constructors you could for example implement the additional ones as classmethods:
class Vector:
x = 0.0
y = 0.0
def __init__(self, x, y):
self.x = x
self.y = y
#classmethod
def from_list(cls, coordinates):
return cls(coordinates[0], coordinates[1])
# you could also use unpacking:
# return cls(*coordinates)
Test:
>>> v1 = Vector(1,3)
>>> print(v1.x)
1
>>> v2 = Vector.from_list([2, 1])
>>> print(v2.x)
2
Python doesn't do overloaded constructors - its a dynamic language and has no preknowledge of type that would allow this to happen. Your code defines an __init__ then replaces it completely with a second __init__. If you want to do something like this, you could define a factory method with the alternate signature and call that.
You do not have overloaded constructors: the second method definition overwrites the first. Thus, your only surviving constructor takes only two arguments. You supplied 3 -- self is implied.

rename class variables in python without the self

Not sure how to quite phrase it, but here's the deal. I have a script where every variable is defined globally, but later I want to convert the script into a class for better encapsulation.
However, all the variables I used in the script needs to be converted into object variables. I would have changed something like
x = 5
into
self.x = 5
And after doing that all the functions in the script needs to be turned into methods of the class, however, most of the methods are mathematical formulas, and refactoring something as clean as
z = x ** y + x
into
z = self.x ** self.y + self.x
really hurts readability.
So as a solution to this I've been typing these really awkward re-naming at the beginning of the methods:
def method(self, ...):
x = self.x
y = self.y
...
It makes the formulas readable but typing all that re-naming is really painful, is there a more elegant way of doing this?
self is only a suggested name. I would encourage you to use it, but in some cases it is better to shorten it.
class A:
x = None
y = None
def calculate_z(s):
return s.x ** s.y + s.x
foo = A()
foo.x = 4
foo.y = 2
foo.calculate_z() # 20
Fun fact: you could even use unicode characters, like ® (in Python 3, that is).
def calculate_z(®):
return ®.x ** ®.y + ®.x
Well, there could be some other solutions, but they're all ugly hacks at most.
You can make the code possibly less awkward by using multiple assignment though:
x, y = self.x, self.y
In addition x and y are faster to use in CPython than self.x and self.y, because the latter ones would need a costly attribute lookup for every use.

When to store things as part of an instance vs returning them?

I was just wondering when to store things as part of a class instance versus when to use a method to return things. For example, which of the following would be better:
class MClass():
def __init__(self):
self.x = self.get_x()
self.get_y()
self.z = None
self.get_z()
def get_x(self):
return 2
def get_y(self):
self.y = 5 * self.x
def get_z(self):
return self.get_x() * self.x
What are the conventions regarding this sort of thing and when should I assign things to self and when should I return values? Is this essentially a public/private sort of distinction?
You shouldn't return anything from __init__.
Python is not Java. You don't need to include get for everything.
If x is always 2 and y is always 10 and z is always 12, that is a lot of code.
Making some assumptions, I would write that class:
class MClass(object):
def __init__(self, x):
self.x = x
def y(self):
return self.x * 5
def z(self):
return self.x + self.y()
>>> c = MClass(2)
>>> c.x
2
>>> c.y() # note parentheses
10
>>> c.z()
12
This allows x to change later (e.g. c.x = 4) and still give the correct values for y and z.
You can use the #property decorator:
class MClass():
def __init__(self):
self.x = 2
#property
def y(self):
return 5 * self.x
#here a plus method for the setter
#y.setter
def y(self,value):
self.x = y/5
#property
def z(self):
return self.x * self.x
It's a good way of organizing yours acessors
There's no "conventions" regarding this, AFAIK, although there're common practices, different from one language to the next.
In python, the general belief is that "everything is public", and there's no reason at all to have a getter method just to return the value of a instance variable. You may, however, need such a method if you need to perform operations on the instance when such variable is accessed.
Your get_y method, for example, only makes sense if you need to recalculate the expression (5 * self.x) every time you access the value. Otherwise, you should simply define the y variable in the instance in __init__ - it's faster (because you don't recalculate the value every time) and it makes your intentions clear (because anyone looking at your code will immediately know that the value does not change)
Finally, some people prefer using properties instead of writing bare get/set methods. There's more info in this question
I read your question as a general Object Oriented development question, rather than a python specific one. As such, the general rule of member data would be to save the data as a member of the class only if it's relevant as part of a particular instance.
As an example, if you have a Screen object which has two dimensions, height and width. Those two should be stored as members. The area associated with a particular instance would return the value associated with a particular instance's height and width.
If there are certain things that seem like they should be calculated on the fly, but might be called over and over again, you can cache them as members as well, but that's really something you should do after you determine that it is a valid trade off (extra member in exchange for faster run time).
get should always do what it says. get_y() and get_z() don't do that.
Better do:
class MClass(object):
def __init__(self):
self.x = 2
#property
def y(self):
return 5 * self.x
#property
def z(self):
return self.x * self.x
This makes y and z always depend on the value of x.
You can do
c = MClass()
print c.y, c.z # 10, 4
c.x = 20
print c.y, c.z # 100, 400

Overloading Addition with Python Vectors

As you can see i've created a function that allows me to create and alter a vector. Now i'm trying to add vectors together using def __add__(self, y). However, i'm getting an IndexError. Is there anything obvious you can see wrong with my code because I'm getting stuck.
def __add__(self, y):
self.vector = []
for j in range(len(self.vector)):
self.vector.append(self.vector[j] + y.self.vector[j])
return Vec(self.vector)
You've got a few issues in your code:
When you do self.vector = [], you are basically clearing your vector. That's makes it impossible to add it to the other vector.
When you do return Vec(self.vector), you're passing a list to the Vec constructor - but you've defined it to take a vector length.
You can only add vectors that are the same length as each other - you don't check that that is the case.
The following is a possible implementation of __add__ with those problems addressed:
def __add__(self, y):
size = len(self.vector)
if size != len(y.vector):
raise ValueError("Vectors must be the same size.")
result = Vec(size)
for j in range(size):
result.vector[j] = self.vector[j] + y.vector[j]
return result

Categories