Call a method variable from outside the class - python-3.x

I'm trying to make a class that contains an array and then name the columns of the array with instance variables and return the value of the cell in that row/column externally by filling in the row value from calling the method index_value.
However I get this error every time I try to call it.
AttributeError: 'function' object has no attribute 'value'
I've tried
import numpy as np
class stuff:
array = np.zeros((5,5), dtype = float)
def index_value(self, arr_index_number = 0):
self.value = self.array[arr_index_number,0]
self.value_2 = self.array[arr_index_number,1]
def index_number(self, n = 0):
return n
stuff = stuff()
stuff_index_value = stuff.index_value
print(stuff_index_value.value(1))
and with an init
import numpy as np
class stuff:
def __init__(self):
self.array = np.zeros((5,5), dtype = float)
def index_value(self, arr_index_number = 0):
self.value = self.array[arr_index_number,0]
self.value_2 = self.array[arr_index_number,1]
stuff = stuff()
stuff_index_value = stuff.index_value
print(stuff_index_value.value(1))
I've tried
print(stuff_index_value.value(1))
and
print(stuff.value(1))
What am I doing wrong? :(
To clarify what I want to do, I want to store every column in the array as its own variable. Each column represents a different category of data so I need them to be saved to their own variable.
Then I want to be able to call the value of the row/column by using the method and inputting the row number.
so in
self.value_2 = self.array[self.arr_index_number,1]
if arr_index_number == 1 then the value that would be returned would be the value of self.array[1,1].
In order to change the value of arr_index_number I need to call it from the method 'index_value'.
So if self.array[1,1] = 5 then I would need to call it with the equivalent of
stuff.index_value.value_2(1)
where (1) is the arr_index_number in the method in order to get that value.
The trouble here is I can't just call the method and be done it with, I need to call the variables within the method and their transformed values.
I can't figure out the correct syntax to do this.

Related

How can I assign a custom object to xarray data values?

I have created a DataArray using xarray successfully:
df_invoice_features = xr.DataArray(data=None,
dims={"y", "x"},
coords={"y": unique_invoices, "x": cols})
I created a custom class and assigned one value of xarray to the instance of this class:
class MyArray:
def __init__(self, s):
self.arr = np.array((s))
def set(self, idx, val):
self.arr[idx] = val
def get(self):
return self.arr
df_invoice_features.loc['basket_value_brand', invoice_id] = MyArray(len_b)
It is created successfully again:
But when I want to update the array of this class instance:
df_invoice_features.loc['basket_value_brand', invoice_id].set(0, 10)
It returns this error:
AttributeError: 'DataArray' object has no attribute 'set'
How can I use an array, dictionary or my custom object inside xarray data values?
So df_invoice_features.loc['basket_value_brand', invoice_id] doesn't actually return MyArray(len_b). Instead, it returns an xarray DataArray; specifically the subset of your full DataArray at the coordinate ['basket_value_brand', invoice_id]. This doesn't just include the value at that location (MyArray(len_b)), but also all the other information stored at that DataArray location; i.e., your coordinates, metadata, etc.
If you want to access the actual value at that location, you'll have to use .values; i.e.,
df_invoice_features.loc['basket_value_brand', invoice_id].values
That should get you the MyArray(len_b) you're looking for. However, I'm not entirely clear what you would like to do with that class. If you're trying to change the value of your DataArray at that location, this bit of the xarray docs in particular may be useful to review.

Class objects not being callable after instantiation

class Swimmers:
""" Creates objects for each swimmer with unique details"""
instances = []
def __init__(self, fName = "None", lName = "None", house = "None", time = "None"):
self.fName = getfName()
self.lName = getlName()
self.house = getHouse()
self.time = getTime()
self.__class__.instances.append(self)
#classmethod
def printInstances(cls):
for instance in cls.instances:
print(instance)
def test():
style, swimmerNumber = raceDetails()
for x in range(int(swimmerNumber)):
y = re.sub(".0", "", str(x))
string = "swimmer" + y
print("\n" + string + "\n")
string = Swimmers()
x -= 1
I need to create a module that takes various inputs and saves each iteration as a class object. The function raceDetails() simply gets the type of race and the number of swimmers, nothing wrong with that part. The functions getX() are simply input functions with some error checking. The issue is that trying to call the objects or any of their variables after everything has been entered simply gives me:
>>> swimmer0.fName
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
swimmer0.fName
NameError: name 'swimmer0' is not defined
I've added a list of every object created by the class ('instances') which prints:
<__main__.Swimmers object at 0x04182F88>
<__main__.Swimmers object at 0x04182E50>
and so on, which, combined with the working getX() functions, means the objects are being instantiated perfectly fine. I've tried everything I can think of, including nonlocals, changing scopes, adding intermediary functions, but none of it seems to work. The only thing I can think of is an issue with reference generation in the module namespace.
It's not essential that I use classes for this, and I could very easily use dictionaries or the like, but I want to try and learn classes as best as I can.
Using Windows 10, Python 3.9.2 32-bit
The problem is you're setting the string variable equal to the variable name you want ('swimmer0', 'swimmer1'...), but then you set string equal to the Swimmers class. Dynamically setting variables names is possible in python, but typically you'll want to use a dictionary (or another collections object) to store the objects.
def test():
style, swimmerNumber = raceDetails()
swimmers_dict = {}
for x in range(int(swimmerNumber)):
y = re.sub(".0", "", str(x))
string = "swimmer" + y
print("\n" + string + "\n")
swimmers_dict[x] = Swimmers()
x -= 1
return swimmers_dict

Adding instance attribute value to other instance's attribute, where is my mistake?

I have tried to find an explanation of why the following...
class First():
def __init__(self, value):
self.value = value + object_second.value_2
class Second():
def __init__(self):
self.value_2 = 0
def change_value_2(self):
self.value_2 = 10
object_second = Second()
object_first = First(10)
print(object_first.value)
object_second.change_value_2()
print(object_first.value)
...returns:
10
10
And not, what I expected:
10
20
Does the first instance's attribute not get updated automatically when the second instance's attribute gets updated, even though the first instance's attribute's value is dependent on the latter?
Just have a look at the code you have written. you first create the Second object which will create it with value2 as 0. you then create the first object which will assign to its attribute value the value that you passed in (10) and the value of value2 of second which is 0. 10 + 0 = 10 so the result 10 is assigned to value of first. When you change value2 later that doesnt affect first as it already evaluated and added them. changeing value2 later will have no effect on value
So your value in first will only be evaluated when first is created. it wont update when you change second. you can see this if you create another first object after you change second. the additional first object will have its value as 20 as it was created after second had its value set to 10
class First():
def __init__(self, value):
self.value = value + object_second.value_2
class Second():
def __init__(self):
self.value_2 = 0
def change_value_2(self):
self.value_2 = 10
object_second = Second()
object_first = First(10)
print(object_first.value)
object_second.change_value_2()
print(object_first.value)
object_first2 = First(10)
print(object_first2.value)
OUTPUT
10
10
20
Also you should never write object instances directly in your class. If your class requires the object instance then you should pass it in as part of the call to create.

How can I make this body of code through a for loop?

So, I'm trying to get this code to work in a cleaner way, mainly, through the use of a for loop, but having a really hard time trying to do so. I haven't been able to make a loop that assigns each value of the dictionary to a correspondent variable, so it can be used in the class. For context, the dictionary contains values obtained from another class, I just put those in the dict and sent it to this class, so I don't need to calculate those again.
def get_ipr_data(self):
self.reservoir_result_dict = ReservoirDataFrame.reservoir_result_dict
self.pb = self.reservoir_result_dict.get("pb")
self.rs = self.reservoir_result_dict.get("rs")
self.bo = self.reservoir_result_dict.get("bo")
self.uo = self.reservoir_result_dict.get("uo")
self.re = self.reservoir_result_dict.get("re")
self.j_index = self.reservoir_result_dict.get("j_index")
self.q_max = self.reservoir_result_dict.get("q_max")
self.pws = self.reservoir_result_dict.get("pws")
self.qb = self.reservoir_result_dict.get("qb")
You can use setattr function
for name in ["pb", "rs", "bo", "uo", "re", "j_index", "q_max", "pws", "qb"]:
setattr(self, name, self.reservoir_result_dict.get(name))
Documentation of setattr:
https://docs.python.org/3/library/functions.html#setattr
Delegating attributes is done by defining the __getattr__ method. You should store the dictionary only and then define __getattr__.
class Foo:
...
def get_ipr_data(self):
self.reservoir_result_dict = ReservoirDataFrame.reservoir_result_dict
def __getattr__(self, item):
return self.reservoir_result_dict[item]

Iterating through class variables in python

Please correct my code
PS - i'm fairly new to python
class Contact:
def __init__(self,cid, email):
self.cid=cid
self.email=email
def ind(contacts):
index={}
#Code here
return index
contacts = [Contact(1,'a'),
Contact(2,'b'),
Contact(3,'c'),
Contact(4,'a')]
print(ind(contacts))
Need the output to be like -
{'a':[1,4], 'b':2, 'c':3}
The following methods create list values like:
{'a':[1,4], 'b':[2], 'c':[3]}
I can't imagine why this wouldn't be fine, but I've added a method at the end that gets your specific output.
This doesn't maintain order of the emails:
def ind(contracts):
index={}
for contract in contracts:
index.setdefault(contract.email, []).append(contract.cid)
return index
To maintain order (e.g. start with 'a'), add from collects import OrderedDict to the top of your file and then the method is:
def ind(contracts):
index = OrderedDict()
for contract in contracts:
index.setdefault(contract.email, []).append(contract.cid)
return index
The printout of index will look different, but it acts the same as a normal dict object (just with ordering).
Exact output (with ordering):
def ind(contracts):
index = OrderedDict()
for contract in contracts:
if contract.email in index:
value = index[contract.email]
if not isinstance(value, list):
index[contract.email] = [value]
index[contract.email].append(contract.cid)
else:
index[contract.email] = contract.cid
return index

Resources