A few days ago, I asked about passing values between instances of classes here is my post here
That problem was easy to fix especially the movement.
But now I can't pass objects between methods.
Example code:
class MyClassA(object):
def function1(self):
entry = input("Insert a value ::: ")
b = MyClassB(entry) #To pass the variable entry to class MyClassB
d = MyClassB()
d.function2()
c = MyClassC(b.k) #Initializied MyClassC to be ready for receive the value p
self.x = d.f #To get back the value k from MyClassB function2()
print(self.x)
self.x1 = c.p #To get back the value k from MyClassC
print(self.x1)
class MyClassB(object):
def __init__(self,M):
self.f = M
self.k = 0
def function2(self):
self.k = self.f * 10 # k will contain (the value entry from MyClassA *10)
c = MyClassC(self.k) #To pass variable k to class MyClassC
class MyClassC(object):
def __init__(self,passedVar):
self.p = passedVar + 0.1 # p will contain (the value entry from MyClassB + 0.1)
h = MyClassA()
h.function1()
Otherwise whenever i try to work with instanace it gonna work right but between methods not that such fixed.
as last time this my code should give this way of result :
Insert a value ::: 9 (assume the user typed 9 here)
so the output should be:
90
90.1
here my code complation say
d = MyClassB()
TypeError: __init__() takes exactly 2 arguments (1 given)
Any way I can fix my code > It doesn't need to work only with instances; I need some function inside some class
You need to pass something to the constructor for MyClassb()...
Ok My problem is
d = MyClassB()
d.function2()
Statu is Fixed now, i got the way !!!
Correct code is this way :
class MyClassA(object):
def function1(self):
entry = input("Insert a value ::: ")
b = MyClassB(entry) #To pass the variable entry to class MyClassB
b.function2()
c = MyClassC(b.k) #Initializied MyClassC to be ready for receive the value p
self.x = b.f #To get back the value k from MyClassB function2()
print(self.x)
self.x1 = c.p #To get back the value k from MyClassC
print(self.x1)
class MyClassB(object):
def __init__(self,M):
self.f = M
def function2(self):
self.k = self.f * 10 # k will contain (the value entry from MyClassA *10)
c = MyClassC(self.k) #To pass variable k to class MyClassC
class MyClassC(object):
def __init__(self,passedVar):
self.p = passedVar + 0.1 # p will contain (the value entry from MyClassB + 0.1)
h = MyClassA()
h.function1()
Related
I was wondering if there is a way for a class to define a method that behaves like a static method (can be called without an instance variable) and a regular method (can be called with an instance variable).
Im making an RSA module that would help me solve RSA problems, the initialization goes like this:
class RSA:
def __init__(self, n: int, e: int, c: int, p=None, q=None, phi=None):
self.n = n
self.e = e
self.c = c
self.p = p
self.q = q
assert p == None or gmpy2.is_prime(p), 'p must be prime'
assert q == None or gmpy2.is_prime(q), 'q must be prime'
self.phi = phi
and in that class, there is a method that would factorize n into p and q which goes like this (the algorithm used is irrelevant so I wont bother explaining):
def fermat_factorization(self, n=None):
if n == None:
n = self.n
t_ = gmpy2.isqrt(n)+1
counter = 0
t = t_ + counter
temp = gmpy2.isqrt((t * t) - n)
while((temp * temp) != ((t * t) - n)):
counter += 1
t = t_ + counter
temp = gmpy2.isqrt((t * t) - n)
s = temp
p = t + s
q = t - s
return p, q
that implementation does not work. What I wanted to do is for that method to be dynamic, i.e. can be called externally by simply
p, q = RSA.fermat_factorization(n) # n is some large number
yet can also be called on an instance like:
s1 = RSA(n, 65537, c) # c and n is some large number
p, q = s1.fermat_factorization() # without specifying n because it is already an instance attribute
In python, you use modules for that kind of stuff, not classes:
in rsa.py
def fermat_factorization(n):
"""Ordinary function"""
class RSA:
def fermat_factorization(self):
"""Method"""
return fermat_factorization(self.n)
somewhere else:
import rsa
x = rsa.fermat_factorization(100)
obj = rsa.RSA(...)
y = obj.fermat_factorization()
Having a single function that behaves some way or another depending on how it's called is a recipe for disaster. Don't do that.
Recently I was learning the sequence alignment algorithm. After I got the alignment matrix, I could find an optimal path, but I was in trouble when I was looking for multiple optimal paths (backtracking)!
My idea is to store the results of multiple paths with multiple instances, and finally loop through all instances of the base class to get the answer.
I know the following conditions:
What conditions to exit recursion
When do I need to create a new instance and when I don't create it?
But the problem is in the second condition. I don't know how many optimal results there are, and I don't know how many new instances will be created.
So I want to be able to dynamically generate an instance name with a variable.
I don't know how to do this:
# those equivalent to new_instance_name = ResultSeq()
a="new_instance_name"
create_new_instance(a,ResultSeq)
My result base class is ResultSeq:
class KeepRefs(object):
"""
reference:https://stackoverflow.com/questions/328851/printing-all-instances-of-a-class#comment167339_328851
"""
__refs__ = defaultdict(list)
def __init__(self):
self.__refs__[self.__class__].append(weakref.ref(self))
#classmethod
def get_instances(cls):
for inst_ref in cls.__refs__[cls]:
inst = inst_ref()
if inst is not None:
yield inst
class ResultSeq(KeepRefs):
"""
save two
"""
def __init__(self, seq1="", seq2=""):
super(ResultSeq, self).__init__()
self.seq1 = seq1
self.seq2 = seq2
Below is my recursive code:
def multi_backtracking(self, array, i, j, result_seq):
"""
:param array: V, E, F
:param i: row
:param j: col
:param result_seq: new instance of the class ResultSeq
:return: Multiple alignment results
"""
def create_new_obj(name, obj):
"""
I don't know how to do this.
"""
pass
if i == 0 and j == 0:
pass
else:
if array is self.array_V:
if sum(pass_judgement) == 1:
"""
An optimal path without creating a new instance.
"""
self.multi_backtracking(self.array_V, i, j, result_seq)
else:
"""
Multiple paths, need to create a new instance
"""
new_instance_name = "xxx"
create_new_obj(new_instance_name, ResultSeq)
...
if pass_judgement[0]:
result_seq.seq1 = self.origin_seq.seq1[i - 1] + result_seq.seq1
result_seq.seq2 = self.origin_seq.seq2[j - 1] + result_seq.seq2
self.multi_backtracking(self.array_V, i - 1, j - 1, new_instance_name)
if pass_judgement[1]:
self.multi_backtracking(self.array_E, i, j, new_instance_name)
if pass_judgement[2]:
self.multi_backtracking(self.array_F, i, j, new_instance_name)
This is just one of my solutions. If there are better suggestions, I will be happy to accept them, thank you!
You do not need names to store variables - you can use a simple list to store your instances:
class A:
def __init__(self,value):
self.value = value
def __repr__(self):
return f" _{self.value}_ "
def rec(i):
"""Recursive function, returns a list of instances of class A with decreasing
value i"""
if i < 0:
return []
return [A(i)] + rec(i-1)
k = rec(5)
print(k)
Output:
[ _5_ , _4_ , _3_ , _2_ , _1_ , _0_ ]
You can acccess your instances inside your list by indexing:
print(k[2]) # _3_
print(k[2].value + k[3].value) # 5
If you really need names, you can use a dictionary to store them - that is about the same as your existing baseclass KeepRefs does (*):
data = { "Instance1" : A(42), "Instance2" : A(3.141)}
print(data)
print( data["Instance1"].value + data["Instance2"].value )
Output:
{'Instance1': _42_ , 'Instance2': _3.141_ }
45.141
Most of the time when you need user generated "names" for variables you should very strongly reconsider your options.
(*) Your baseclass does not keep non-referenced instances around, a real dict will prevent garbage collecting:
k1 = ResultSeq("A","B")
k2 = ResultSeq("C","D")
k3 = ResultSeq("E","F")
for g in ResultSeq.get_instances():
print(g.seq1, g.seq2)
k2 = None # no instance of k2 anywhere
k3 = None # no instance of k3 anywhere
for g in ResultSeq.get_instances():
print(g.seq1, g.seq2)
A B
C D
E F
A B # 2.print loop after removing instances k2,k3
Documentation:
https://docs.python.org/3/library/weakref.html
I have two self-defined classes, one is a child of the gurobipy-class and is supposed to make a lp-model. The other one I made to store variables. Now I want to store some variables of the model class in the variables class.
Here are my classes:
class Model(gb.Model):
def __init__(self):
super().__init__()
def create_model(self, var):
dim = var.dimensions()
# variables
x = self.addVars(dim[0], dim[1], vtype=gb.GRB.BINARY, name="x")
D_l = self.addVars(dim[1], lb=0, name='D_l')
D_max = self.addVar(lb=0, name='D_max')
# objective
self.setObjective(D_max, gb.GRB.MINIMIZE)
# constraints
self.addConstrs((x.sum(i, '*') == 1 for i in range(dim[0])), name="b")
self.addConstrs((D_max >= D_l[l] for l in range(dim[1])), name="c")
self.addConstrs((D_l[l] >= var.dist_mat()[i, j] * (x[i, l] + x[j, l] - 1) for i in range(dim[0])
for j in range(dim[0]) for l in range(dim[1])), name='a')
self.update()
class Variables:
def __init__(self, data, number_of_clusters, neighbourhood_size):
self.data = data
self.number_of_clusters = number_of_clusters
self.neighbourhood_size = neighbourhood_size
self.variables_before = None
self.variables_now = None
self.ofv_before = None
self.ofv_now = None
self.x = None
def dist_mat(self):
from scipy.spatial import distance_matrix
return distance_matrix(self.data, self.data)
def dimensions(self):
from numpy import shape
data_objects = shape(self.data)[0]
number_of_clusters = self.number_of_clusters
return data_objects, number_of_clusters
def print_dist_mat(self):
print(self.dist_mat())
It's the x-variable I want to store. First, I tried to store it in the instance of the Model-class. I added to the init-function this line self.x = None. But it raise an AttributeError: 'x' is not a model attribute. I guess, this is because the gurobipy-class doesn't have a x attribute.
Next, I wanted to store it in an instance of the variable-class. I wanted to write a function in the model class, which should do the trick. This is the function:
def store_x(self, var):
var.x = self.x
Then, I got this error: gurobipy.GurobiError: Unable to retrieve attribute 'x', I can't understand why.
I can't even access the x-variable from outside the function. I can print it from inside the function, but nothing more. The problem is, I need this x-variable in a later stage.
How can I achieve this? How can I store the x-variable to access it at a later point? It doesn't have to be in the variable-class, any other solution is appreciated as well.
Ok first off I see an issue with Your code:
def store_x(self, var):
var.x = self.x
It Needs to be changed to :
def store_x(self, var):
self.x = var.x
This is because whatever you send in the 'var' parameter will only be a copy of whatever you actually passed. And then its scope will only last to the end of that store_x method. So instead you pass that copy and tell your variable class instance to store it inside it's x value.
As for the error you got with:
self.x = None # inside your Model class
I'm not sure why, as I tried the following and it runs fine:
class Variables:
def __init__(self):
self.data = data
self.number_of_clusters = number_of_clusters
self.neighbourhood_size = neighbourhood_size
self.variables_before = None
self.variables_now = None
self.ofv_before = None
self.ofv_now = None
self.x = None
So I'm updating my answer with a deeper example after getting clarification on what is needed. Here are two skeleton classes named 'Variables', 'Model', respectivly:
class Variables:
def __init__(self):
self.data = None
self.number_of_clusters = None
self.neighbourhood_size = None
self.variables_before = None
self.variables_now = None
self.ofv_before = None
self.ofv_now = None
self.x = None
def get_x(self,modelx):
self.x = modelx
class Model:
def __init__(self):
self.x = ({}, {})
# create your class instances here
newVar = Variables()
newModel = Model()
# one way to assign your Variable class's x attribute the tuple dict in question.
newVar.x = newModel.x
# alternate way is to create a function inside your Variable class that updates the x variable based on the argument you send it.
newVar.get_x(newModel.x)
I want to access the value of gurobi variable self.a and self.b here but its returning 0.0. How can I access the value of these variables. The code is below
from gurobipy import GRB, Model
class abc(object):
def __init__(self):
self.model = Model()
def creatingvarriables(self):
self.a = self.model.addVar(lb=0, vtype=GRB.CONTINUOUS, name="y_")
self.b = self.model.addVar(lb=0, vtype=GRB.CONTINUOUS, name="q_")
self.model.update()
def constraint1(self):
lhs1 = self.model.getVarByName("y_")
lhs1 = 2
rhs1 = self.model.getVarByName("q_")
rhs1 = 3
self.model.update()
self.model.addConstr(lhs1, GRB.LESS_EQUAL, rhs1)
def printvalues(self):
self.model.optimize()
#self.model.printAttr('')
print self.a.X
print self.b.X
if __name__ == "__main__":
newobject = abc()
newobject.creatingvarriables()
newobject.constraint1()
newobject.printvalues()
You can access it's value by calling the variable's *.X attribute, as explained in GUROBI's documentation. For reference, the direct link to the attribute: X Attribute
You are correctly accessing the variable values through the X attribute. The reason why you get confused by the zero solution is an error in the method constraint1:
lhs1 = self.model.getVarByName("y_")
lhs1 = 2
rhs1 = self.model.getVarByName("q_")
rhs1 = 3
self.model.update()
self.model.addConstr(lhs1, GRB.LESS_EQUAL, rhs1)
First you assign to lhs1 and rhs1 references to the created variables, but then you overwrite them with numbers. Effectively you are adding the constraint 2 <= 3, which is satisfied independently of y_ and q_. Hence, setting y_ and q_ to zero is an optimal solution.
class MyClassA(object):
def __init__(self):
entry = input("Insert a value ::: ")
b = MyClassB(entry) #To pass the variable entry to class MyClassB
c = MyClassC() #Initializied MyClassC to be ready for receive the value p
self.x = b.f #To get back the value f from MyClassB
print(self.x)
self.x1 = c.p #To get back the value f from MyClassC
print(self.x1)
class MyClassB(object):
def __init__(self, M):
self.f = M * 10 # f will contain (the value entry from MyClassA *10)
c = MyClassC(self.f) #To pass variable f to class MyClassC
class MyClassC(object):
def __init__(self,passedVar):
self.p = passedVar + 0.1 # p will contain (the value entry from MyClassB + 0.1)
h = MyClassA()
Above is my sample code, first of all it will ask for a value and store it into variable named entry.
Then the second class named MyClassB will recover the value inside entry, after processing the entry value, a new one will be stored into new variable named f which will be passed to third class named MyClassC then also back to first class.
Finally the third class does some processing of the f value and stores it into yet another variable p.
That's how my code should work when the user runs the program, and this is what it would look like:
Insert a value ::: 9 (assume the user typed 9 here)
so the output should be:
90
90.1
Unfortunately my problem is that passing the value from MyClassC to myClassA doesn't work.
It says I must pass it two argument from the first class but it'a going to get the value after executing the 2st class.
I think that I have problem with initializing instances, could someone correct my code to work the way I described?
The problem you're having is because there are two independent instances of MyClassC being created, one in MyClassA.__init__() and a separate one in MyClassB.__init__().
The easy way to fix it — not necessarily the best — would be to make MyClassB.__init__() store the MyClassC instance it creates in yet another instance attribute, and then refer to the attribute of that object when you want to retrieve the value of p.
Here's what I mean:
class MyClassA(object):
def __init__(self):
entry = input("Insert a value ::: ")
b = MyClassB(entry) # To pass the variable entry to class MyClassB
####### c = MyClassC() # Initializied MyClassC to be ready for receive the value p
self.x = b.f # To get back the value f from MyClassB
print(self.x)
self.x1 = b.c.p # To get back the value p from MyClassC instance created in MyClassB
print(self.x1)
class MyClassB(object):
def __init__(self, M):
self.f = M * 10 # f will contain (the value entry from MyClassA *10)
self.c = MyClassC(self.f) # Pass variable f to class MyClassC and save instance
class MyClassC(object):
def __init__(self, passedVar):
self.p = passedVar + 0.1 # p will contain (the value entry from MyClassB + 0.1)
h = MyClassA()
In line
c = MyClassC()
it should be
c = MyClassC(b.f)
Or you could set the value p to the class MyClassC
class MyClassC(object):
def __init__(self, passedVar):
MyClassC.p = passedVar + 0.1
but keep in mind that this situation can happen
class T(object):
def __init__(self, x):
T.x = x
if __name__ == '__main__':
t1 = T(3)
print t1.x, T.x
t1.x = 1
print t1.x, T.x
t2 = T(2)
print t1.x, t2.x, T.x
# output:
3 3
1 3
1 2 2