The problem in the code is that Vector.numerical_vector is a list of copies of floats, but I need it to be list of references, so when Vector.vector[n].value is changed, Vector.numerical_vector[n] is changed to the same value as well.
Thanks for help in advance!
class Var:
def __init__(self, val):
self.value = float(val)
def __float__(self):
return self.value
class Vector:
def __init__(self, vector):
self.vector = vector
self.numerical_vector = [float(x) for x in vector]
vars = [Var(i) for i in range(5)]
vector = Vector(vars)
There's no way to do that in python. What you could do is make numerical_vector an object that, when accessed, returns the float value of the corresponding vector item. Eg
class VectorWrapper:
def __init__(self, vector):
self.vector = vector
def __getitem__(self, i):
return float(self.vector[i])
and set self.numerical_vector = VectorWrapper(self.vector)
If you have to return a float representation when self.numerical_vector[i] is referenced,
You might want to employ a property for that.
class Vector:
def __init__(self, vector):
self.vector = vector
#property
def numerical_vector(self):
return [x.value for x in self.vector]
Now vector.numerical_vector will always be synchronized. A drawback of this method is that it is recomputed each time you access it, some it may not be adapted to your specific application.
If performance is an issue, you could add __getitem__ and __setitem__ methods to Vector as follows:
class Vector:
def __init__(self, vector):
self.vector = vector
self.numerical_vector = [float(x) for x in vector]
def __getitem__(self, i):
return self.vector[i]
def __setitem__(self, i, val):
self.vector[i] = val
self.numerical_vector[i] = float(val)
In that case, if you set vector_instance[i], then vector_instance.numerical_vector[i] will be also modified. But if you want to modify vector_instance.vector[i] directly, then synchronicity will be broken.
Depending on the use case, you can use either of the two approaches. Both have limitations but I don't think much more can be done.
Related
I have two classes, for the example I will call them "Point" and "Vector" (like in math). I want one of the classes be called by the other to "convert" for example a point into the according vector ((1,2,1) -> (1,2,1)T).
argsintfloat = lambda l: all(isinstance(i, (int,float,complex)) for i in l)
class Point:
def __init__(self, *args):
if not argsintfloat(args):
raise ValueError("non-numeral values are not supported")
self.coordinates = args
def Vector(self):
return Vector(*self.coordinates)
class Vector:
def __init__(self, *args):
if not argsintfloat(args):
raise ValueError("non-numeral values are not supported")
self.components = args
def Point(self):
return Point(*self.components)
Now when for example calling the following:
point1 = Point(1,2,3,4)
vector1 = Vector(point1)
I just arrive at the ValueError
ValueError: non-numeral values are not supported
as expected when the values given aren't int, float or complex. I understand why this problem is occuring; the class Vector is called instead of the function Vector in the class Point and since a class object isn't an int, float or complex... Normally I'd just call that function with
point1.Point()
but I don't want to solve this problem with that. I want to make this as visually easy as possible without further specifying the args types conversion in init(). Anyone have an idea on how to achieve that?
While you could examine the arguments to Vector.__init__ to see if you got multiple numbers or a single Point, it would be better to use a class method to decompose the Point into values that can be passed to __init__.
class Vector:
def __init__(self, *args):
if not argsintfloat(args):
raise ValueError("non-numeral values are not supported")
self.components = args
def to_point(self):
return Point(*self.components)
#classmethod
def from_point(cls, p: Point):
return cls(*p.components)
point1 = Point(1,2,3,4)
vector1 = Vector.from_point(point1)
The same argument applies to your Point class:
class Point:
def __init__(self, *args):
if not argsintfloat(args):
raise ValueError("non-numeral values are not supported")
self.coordinates = args
def to_vector(self):
return Vector(*self.coordinates)
#classmethod
def from_vector(cls, v: Vector):
return cls(*v.components)
In mathematical terms, Vector and Point are isomorphic, meaning you can losslessly convert from a value of one type to the other. Specifically, if you have a Point p, then p == Point.from_vector(p.to_vector()), and if you have a Vector v, then v == Vector.from_point(v.to_point()).
I have two sets of numbers
xl=linspace(0.,1,1000)
xu=linspace(0.,1,1000)+0.5
which should form pairwise intervals over which I want to run a polynomial function.
I want to store the resulting values for each interval, as lists within a list.
The only way I can think of is the following:
-Variables
xl=linspace(0.,1,1000)
xu=linspace(0.,1,1000)+0.5
M=[]-the list where the intervals are to be stored
Values=[] # The list where the output of the polynomial function will be stored.
class Interval:
def __init__(self,left,right):
self.left=left
self.right=right
def __repr__(self):
return'[{},{}]'.format(self.left,self.right)
def BuildIntervalFromLists(x,y): (builds the list of intervals)
for i, j in zip(x, y):
M.append(Interval(i,j))
return M
def Polynomial(t): (The function)
3*t**3-2*t**2-5*t-1
def PolynomialFunction(x): (Function to run over all intervals)
for k in x: # The intervals in sequence
for l in k: # The numbers in each interval in sequence
Values.append([Polynomial(l)])
return(Values)
BuildIntervalFromLists(xl,xu)
PolynomialFunction(M)
This, however, gives the error message that I can't run an iteration over an interval.
Is there any way of getting around this problem?
If not, is there a better approach?
There is a special method in python which is called getitem to reach an item inside of an object. You can simply define it as follows:
def __getitem__(self, position):
return self.my_array[position]
As you can see I also define my_array variable inside the class. So the new class implementation will be like this:
class Interval:
def __init__(self,left,right):
self.left=left
self.right=right
self.my_array = [left,right]
def __repr__(self):
return'[{},{}]'.format(self.left,self.right)
def __getitem__(self, position):
return self.my_array[position]
Now, you can see the variables inside of your class thanks to repr and you can iterate them by using getitem
The overall code will be like this:
import numpy as np
xl=np.linspace(0.,1,1000)
xu=np.linspace(0.,1,1000)+0.5
M=[]
Values=[] # The list where the output of the polynomial function will be stored.
class Interval:
def __init__(self,left,right):
self.left=left
self.right=right
self.my_array = [left,right]
def __repr__(self):
return'[{},{}]'.format(self.left,self.right)
def __getitem__(self, position):
return self.my_array[position]
def BuildIntervalFromLists(x,y):
for i, j in zip(x, y):
M.append(Interval(i,j))
return M
def Polynomial(t):
return 3*t**3-2*t**2-5*t-1
def PolynomialFunction(x):
for k in x: # The intervals in sequence
for l in k: # The numbers in each interval in sequence
Values.append([Polynomial(l)])
return(Values)
BuildIntervalFromLists(xl,xu)
PolynomialFunction(M)
I hope it will solve your problem. Best
How do you go about overloading the addition, subtraction, and multiplication operator so we can add, subtract, and multiply two vectors of different or identical sizes? For example, if the vectors are different sizes we must be able to add, subtract, or multiply the two vectors according to the smallest vector size?
I've created a function that allows you to modify different vectors, but now I'm struggling to overload the operators and haven't a clue on where to begin. I will paste the code below. Any ideas?
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 define the __add__, __sub__, and __mul__ methods for the class, that's how. Each method takes two objects (the operands of +/-/*) as arguments and is expected to return the result of the computation.
Nothing wrong with the accepted answer on this question but I'm adding some quick snippets to illustrate how this can be used. (Note that you could also "overload" the method to handle multiple types.)
"""Return the difference of another Transaction object, or another
class object that also has the `val` property."""
class Transaction(object):
def __init__(self, val):
self.val = val
def __sub__(self, other):
return self.val - other.val
buy = Transaction(10.00)
sell = Transaction(7.00)
print(buy - sell)
# 3.0
"""Return a Transaction object with `val` as the difference of this
Transaction.val property and another object with a `val` property."""
class Transaction(object):
def __init__(self, val):
self.val = val
def __sub__(self, other):
return Transaction(self.val - other.val)
buy = Transaction(20.00)
sell = Transaction(5.00)
result = buy - sell
print(result.val)
# 15
"""Return difference of this Transaction.val property and an integer."""
class Transaction(object):
def __init__(self, val):
self.val = val
def __sub__(self, other):
return self.val - other
buy = Transaction(8.00)
print(buy - 6.00)
# 2
docs have the answer. Basically there are functions that get called on an object when you add or multiple, etc. for instance __add__ is the normal add function.
How do you go about overloading the addition, subtraction, and multiplication operator so we can add, subtract, and multiply two vectors of different or identical sizes? For example, if the vectors are different sizes we must be able to add, subtract, or multiply the two vectors according to the smallest vector size?
I've created a function that allows you to modify different vectors, but now I'm struggling to overload the operators and haven't a clue on where to begin. I will paste the code below. Any ideas?
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 define the __add__, __sub__, and __mul__ methods for the class, that's how. Each method takes two objects (the operands of +/-/*) as arguments and is expected to return the result of the computation.
Nothing wrong with the accepted answer on this question but I'm adding some quick snippets to illustrate how this can be used. (Note that you could also "overload" the method to handle multiple types.)
"""Return the difference of another Transaction object, or another
class object that also has the `val` property."""
class Transaction(object):
def __init__(self, val):
self.val = val
def __sub__(self, other):
return self.val - other.val
buy = Transaction(10.00)
sell = Transaction(7.00)
print(buy - sell)
# 3.0
"""Return a Transaction object with `val` as the difference of this
Transaction.val property and another object with a `val` property."""
class Transaction(object):
def __init__(self, val):
self.val = val
def __sub__(self, other):
return Transaction(self.val - other.val)
buy = Transaction(20.00)
sell = Transaction(5.00)
result = buy - sell
print(result.val)
# 15
"""Return difference of this Transaction.val property and an integer."""
class Transaction(object):
def __init__(self, val):
self.val = val
def __sub__(self, other):
return self.val - other
buy = Transaction(8.00)
print(buy - 6.00)
# 2
docs have the answer. Basically there are functions that get called on an object when you add or multiple, etc. for instance __add__ is the normal add function.
I'm fairly new to classes in python, so please be gentle. My script is a tad more complicated than this, but this is essentially what it boils down to:
class primary_state:
def __init__(self,x,y,z):
self.x = x
self.y = y
self.z = z
self.substates=[]
def add_substate(self,i,j,k):
self.substates.append(self.substate(i,j,k))
class substate:
def __init__(self,i,j,k):
self.i = i
self.j = j
self.k = k
state = primary_state(1,2,3)
state.add_substate(4,5,6)
state.add_substate(7,8,9)
Now my question is: is it possible to return an array of values from each object? So for example I'd like to do:
state.substates[:].i
and have it return the values of 4 and 7, but alas substates is a list so it can't handle it. There also must be a more efficient way to do this but I haven't quite figured that out yet. Any advice/thoughts would be greatly appreciated! Thanks.
Use a list comprehension.
[sub.i for sub in state.substates]
This is roughly equivalent to the following:
x = []
for sub in state.substates:
x.append(sub.i)
except shorter, and it's an expression that you can embed in other expressions instead of a series of statements.
You can get the list of substates by calling:
[substate.i for substate in self.substates]
list comprehensions are the way to do it as the other answers point out.
If the only job of the primary state class is to hold subclasses, you can make your class behave like an iterable. In the example you give this is mostly syntactic sugar, but it can be useful. Complete instructions on how to do it are here but it's pretty simple:
class PrimaryState(object): #always use "new style" classes! its 2013!
def __init__(self,x,y,z):
self.x = x
self.y = y
self.z = z
self.substates=[]
def __len__(self):
return len(self.substates)
def __getitem__(self, index):
return self.substates[index]
def __iter__(self):
for sub in substates: yield sub
def __contains__(self, item):
return item in self.substates
def add(self, item):
self.substates.append(item)
This way you can do:
primary = PrimaryState(1,2,3)
primary.add(SubState(4,5,6))
primary.add(SubState(7,8,9))
for item in primary:
print item
# Substate 4,5,6
# Substate 7,8,9
PS: Check out PEP-8, the standard python style guide for naming classes and so on. And use new style classes (inheriting from object). Down the road it's important!