i am take the no. of iteration in for loop running from a different class.
for e in range(1,EPOCHS+1 ):
g=0
for j in range (jin):
g=g+1
print(g)
train_epoch_loss = 0
train_epoch_acc = 0
p1=cross(g)
#pw=pq.save(g)
#p1=pq.get()
model.train()
and saving it in this class and need to use that value.
class cross():
c=0
def init__ (self,value):
self.v = value
print('i entered the classs')
for train_index, test_index in kf.split(x_trainval):
c=c+1
# e1=num()
x_train,x_val=x[train_index],x[test_index]
y_train,y_val=y[train_index],y[test_index]
print("TRAIN:", train_index, "TEST:", test_index)
print("epoch",c)
# print(e1.__getitem__())
if (v == c):
print("compare")
break
train_dataset = classifierdataset(torch.from_numpy(x_train).float(), torch.from_numpy(y_train).long())
val_dataset = classifierdataset(torch.from_numpy(x_val).float(), torch.from_numpy(y_val).long())
test_dataset = classifierdataset(torch.from_numpy(x_test).float(), torch.from_numpy(y_test).long())
train_loader = DataLoader(dataset=train_dataset, batch_size=BATCH_SIZE)
val_loader = DataLoader(dataset = val_dataset, batch_size = 1)
test_loader = DataLoader(dataset = test_dataset , batch_size = 1)
print("train",x_train,"val",x_val)
Now the issues i am having is how to use the set value in the same class.
just put a return statement and take the values accordingly to the return statement.
I think you are asking if you can access obj.value within other methods or self.value within the same class methods .
Maybe this will help you ,
https://medium.com/python-features/class-vs-instance-variables-8d452e9abcbd#:~:text=Class%20variables%20are%20shared%20across,surprising%20behaviour%20in%20our%20code.
Accessing an instance variable within an instance method (a method that accepts self as first argument) -
Correct way -
class Student:
# constructor
def __init__(self, name, age):
# Instance variable
self.name = name
self.age = age
def show(self):
print('Name:', self.name, 'Age:', self.age)
Wrong way -
class Student:
# constructor
def __init__(self, name, age):
# Instance variable
self.name = name
self.age = age
# instance method access instance variable
def show(self):
print('Name:', name, 'Age:', age)
student_obj.show()
gives
NameError: name 'name' is not defined
within some other method you need to have the obj available :
c_obj = cross(5)
def any_other_method(c: cross) -> None:
print("value is ", c.v)
any_other_method(c_obj) prints "value is 5"
Related
I defined a class named Experiment for the results of some lab experiments I am conducting. The idea was to create a sort of database: if I add an experiment, this will be pickled to a db before at exit and reloaded (and added to the class registry) at startup.
My class definition is:
class IterRegistry(type):
def __iter__(cls):
return iter(cls._registry)
class Experiment(metaclass=IterRegistry):
_registry = []
counter = 0
def __init__(self, name, pathprotocol, protocol_struct, pathresult, wallA, wallB, wallC):
hashdat = fn.hashfile(pathresult)
hashpro = fn.hashfile(pathprotocol)
chk = fn.checkhash(hashdat)
if chk:
raise RuntimeError("The same experiment has already been added")
self._registry.append(self)
self.name = name
[...]
While fn.checkhash is a function that checks the hashes of the files containing the results:
def checkhash(hashdat):
for exp in cl.Experiment:
if exp.hashdat == hashdat:
return exp
return False
So that if I add a previously added experiment, this won't be overwritten.
Is it possible to somehow return the existing instance if already existant instead of raising an error? (I know in __init__ block it is not possible)
You can use __new__ if you want to customize the creation instead of just initializing in newly created object:
class Experiment(metaclass=IterRegistry):
_registry = []
counter = 0
def __new__(cls, name, pathprotocol, protocol_struct, pathresult, wallA, wallB, wallC):
hashdat = fn.hashfile(pathresult)
hashpro = fn.hashfile(pathprotocol)
chk = fn.checkhash(hashdat)
if chk: # already added, just return previous instance
return chk
self = object.__new__(cls) # create a new uninitialized instance
self._registry.append(self) # register and initialize it
self.name = name
[...]
return self # return the new registered instance
Try to do it this way (very simplified example):
class A:
registry = {}
def __init__(self, x):
self.x = x
#classmethod
def create_item(cls, x):
try:
return cls.registry[x]
except KeyError:
new_item = cls(x)
cls.registry[x] = new_item
return new_item
A.create_item(1)
A.create_item(2)
A.create_item(2) # doesn't add new item, but returns already existing one
After four years of the question, I got here and Serge Ballesta's answer helped me. I created this example with an easier syntax.
If base is None, it will always return the first object created.
class MyClass:
instances = []
def __new__(cls, base=None):
if len(MyClass.instances) == 0:
self = object.__new__(cls)
MyClass.instances.append(self)
if base is None:
return MyClass.instances[0]
else:
self = object.__new__(cls)
MyClass.instances.append(self)
# self.__init__(base)
return self
def __init__(self, base=None):
print("Received base = %s " % str(base))
print("Number of instances = %d" % len(self.instances))
self.base = base
R1 = MyClass("apple")
R2 = MyClass()
R3 = MyClass("banana")
R4 = MyClass()
R5 = MyClass("apple")
print(id(R1), R1.base)
print(id(R2), R2.base)
print(id(R3), R3.base)
print(id(R4), R4.base)
print(id(R5), R5.base)
print("R2 == R4 ? %s" % (R2 == R4))
print("R1 == R5 ? %s" % (R1 == R5))
It gives us the result
Received base = apple
Number of instances = 2
Received base = None
Number of instances = 2
Received base = banana
Number of instances = 3
Received base = None
Number of instances = 3
Received base = apple
Number of instances = 4
2167043940208 apple
2167043940256 None
2167043939968 banana
2167043940256 None
2167043939872 apple
R2 == R4 ? True
R1 == R5 ? False
Is nice to know that __init__ will be always called before the return of the __new__, even if you don't call it (in commented part) or you return an object that already exists.
I have training and test dataset as Pytorch Tensor objects and I want to change their values from another class, is this somehow possible? The code below does not change their values:
class BO:
def __init__(self):
self.data = DataCollector().df_subset
self.risk = DataCollector().risk_subset.unique(dim=0)
self.device = torch.device('cpu')
self.X_init = None
self.outs_init = torch.zeros(0)
self.y_init = []
if torch.cuda.is_available():
self.device = torch.device('cuda:7')
def create_init_X_Y(self):
'''
Creates the initial X and y values.
'''
model.TrainDataset().df = self.data
_, loss = model.train()
I need to overwrite the value of model.TrainDataset().df with the value of self.data.
class Employee:
company = 'Google'
def __init__(self, name, salaryInput, salIncrement):
self.name = name
self.salaryInput = salaryInput
self.salIncrement = salIncrement
def salary(self):
print('Base salary of {} is ${}'.format(self.name, self.salary))
def increment(self):
print('Increment in salary = ${}'.format(self.salIncrement))
#property
def salaryAfterIncrement(self):
return self.salaryInput + self.salIncrement
#salaryAfterIncrement.setter
def salaryAfterIncrement(self, salaryInput):
self.increment = salaryAfterIncrement - self.salaryInput
abhishek = Employee('Abhishek', 100, 50)
print(abhishek.salaryAfterIncrement)
print(abhishek.increment)
You need to add parenthesis. And BTW, you need to use return in .increment() function. This wouldn't solve your problem but it will print a None. So try -
return 'Increment in salary = ${}'.format(self.salIncrement)
Then use print -
print(abhishek.increment())
Or if you do not want to use return then call the function without print statement -
print('Increment in salary = ${}'.format(self.salIncrement))
Then call the function -
abhishek.increment()
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)
In the last line I get the error that my object ant003 is not defined. But why?
class Ant:
def __init__(self, name):
"""Initializes the data."""
self.name = name
self.food = 0
self.posx = 0
self.posy = 0
print("(Initializing {0})".format(self.name))
def searchFood(self):
self.food = self.food + 1
print("Ant {1} has {0} food.".format(self.food, self.name))
ant001 = Ant("Anton")
ant001.searchFood()
ant002 = Ant("Bob")
ants = {'ant003': None, 'ant004': None}
for name in ants.keys():
ants[name] = Ant(name)
print ants[name]
#print ant001
#print ant003
ant003.searchFood() # NameError: name 'ant003' is not defined
Setting an item of a dictionary does not affect namespace that contains the dictionary.
You can access dictionary value using dict[key]:
ants['ant003'].searchFood()
Did you mean to use globals? (not recommended)
...
for name in ants.keys():
globals()[name] = Ant(name) # <----
ant003.searchFood()