python - how to share variables between two different instances - python

I have seen many posts that shows how to access constant value, by inheritance. that's not my case.
I would like to create two instances from two different modules, and be able to share information/variables between them.
two issues:
1. the classes "dont know" each other, because they are on different files, "import"ing them as modules does not help much in this case
2. how can "print_class" instance can access & change values of variable in "cal_class" instance ?
Please note, I am looking for a way to access value from one instance to another. (in my case, there is allot of information (excel tables) to pass between instances, passing parameters through the "main" function is not practical)
Here is my simplify problem:
cal_class_file.py
class cal_class:
def add(self,first,second)
self.result= first + second
print_class_file.py
class print_class:
def print_sum(self):
result_from_cal_class = ?? <=-# How to get the value from local_calculate.result?
print(result_from_cal_class)
main.py
import cal_class_file
import print_class_file
def main():
local_calculate = cal_class_file.cal_class() # create instance
local_print = print_class_file.print_class(); # create instance that reads values from "local_calculate" instance
local_calculate.add(5,6) # calculate addition
local_print.print_sum() # output: 11
local_calculate.add(4,5) # update values in "local_calculate" instance
local_print.print_sum() # output: 9
How can I get the current (Latest) value for "result_from_cal_class" ?

Pass the value in. You have it right there in your client code:
class print_class:
def print_sum(self, result_from_cal_class):
print(result_from_cal_class)
def main():
local_calculate = cal_class_file.cal_class() # create instance
local_print = print_class_file.print_class(); # create instance that reads values from "local_calculate" instance
local_calculate.add(5, 6) # calculate addition
local_print.print_sum(local_calculate.result) # output: 11
local_calculate.add(4, 5) # update values in "local_calculate" instance
local_print.print_sum(local_calculate.result) # output: 9
Output:
11
9
However, if you mean that your client does this:
def main():
# setup elided ...
# actually call to add is done in another function
local_calculate.add(5, 6) # calculate addition
# actually call to print_sum is done somewhere else:
local_print.print_sum() # output: 11
You could define print_class like this:
class print_class:
def __init__(self, calculator):
self.calculator = calculator
def print_sum(self):
print(self.calculator.result)
Then initialise it like this:
def main():
local_calculate = cal_class_file.cal_class() # create instance
local_print = print_class_file.print_class(local_calculate); # create instance that reads values from "local_calculate" instance
Be careful as this is a little like having a global variable: calculate does something, leaving a result, print picks up the last result.
If you have an unexpected call to calculate between the one you want and the print, you will get unexpected results.

Related

Calculate attributes with subclass parameters

I'm working in small Python program with several classes and subclasses. The main point is that I need to calculate the value of the main class with the attributes of the subclasses.
class Product:
class Extra_1:
value = 5
base_value = 25
final_value = base_value + Extra1.value
The expected output for base_value it would be 30.
However I need to call this class from other file through an import, when I do that I'm not able to get the expected output (50) Instead of that I get 30. It seems like Python its not calculating the value with the formula.
import myprogram
myprogram.Product.Extra.value = 25
print(myprogram.Product.final_value) #Output = 30
I tried to create a function to calculate the final_value and assigning the return as value but I still have the same problem.
class Product:
class Extra_1:
value = 5
creates a class Product with an inner class Extra_1. Technically
a class is also an object, and a code like
base_value = 25
final_value = base_value + Product.Extra_1.value
references an attribute of an object Product and an attribute of a
an object Product.Extra_1. But usually classes are templates to create new objects. A code
x = Product()
y = Product()
creates (instantiates) two new objects of class Product. To achieve
what you want, you can define a special method named __init__ (instantiation automatically invokes this method)
and redesign your program to use instantiation. See
https://docs.python.org/3/tutorial/classes.html
Python Class-Level Variables
There are some things I don't understand. First of all, are Extra, Extra1 and Extra_1 the same subclass? Assuming this and that the last two lines of the first code are inside of the Product class, then this is the expected behavior. Remember that those are class level variables, and, as is, they are evaluated just once. No matter what you do with base_value after the second line got interpreted. And this is true also if you make an instance of the Product class, the class-level variable final_value will not change unless you change it directly.
So, if you still want to use the static subclass attribute base_value and the static class attribute value to calculate your final value (I don't know why) you have to make at least final_value an instance level attribute:
class Product:
class Extra_1:
value = 5
def __init__(self):
self.final_value = Product.base_value + Product.Extra_1.value
base_value = 25
This way, every new instance of Product will calculate its final_value according with the actual value of base_value and value.
import myprogram
#First Product instance will calculate its result with the original values
p1 = myprogram.Product()
#Changing the original value
myprogram.Product.Extra_1.value = 25
#After the modification, creating a new instance
p2 = myprogram.Product()
#This will print the original 30
print(p1.final_value)
#This, in the other hand, will print 50
print(p2.final_value)
Python documentation Class and Instance Variables

Having a variable variable inside a function

I would like to insert the input of a function (lets call it label) into the name of global variable so it is a unique variable based on the input. In an example script this would be something like:
#Script/function 1 - when a file is deleted in a folder it triggers an event
# that runs function on_deleted():
on_deleted()
def on_deleted(event):
if "partoffilename1" in list_of_files:
do_this(label1)
elif "partoffilename2" in list_of_files:
do_this(label2)
#Script/function 2 - for every label input it has its own variable that has some
# calculations/iterations on a 'long' list of globals (!). So for each label it should
# pick its unique global, but also some globals that span across the other labels.
def do_this(label):
#Import globals here, which mostly all the variabeles below
label_min += -1
label_done = abs(label_min)
start_time_label = datime.now()
#and then around 180 more lines of code with each a unique variable for the label
The trick which I can't figure out is how to have the variables be variable based on the input of the second function do_this() which is a label. Currently I had just copy pasted it for one instance and renamed all the variables based on the label.... so a ugly and long code that is hard to maintain.
I looked into using a dict in the second function, but then I still need to address each variable individually to assign it a value.
The other option is probably a class, but I have a long list of variables within one class and I don't know how to avoid the following:
class label:
class_variable_1 = "bla1"
class_variable_2 = "bla2"
def __init__(self, param1, param2, ....., param100):
self.instance_var1 = param1
self.instance_var2 = param2
....
self.instance_var100 = param100
So maybe the question should be, is there a smart solution to avoid a long list of inputs/params for the def __init__ within a class? Or am I bound to that?

Adding attributes to an object

I am trying to find the order of a polynomial. I have created a method called "order" to set self.order to the order of the polynomial it is used on, ie polynomial1.order (p1.order). However, in order to add the order attribute so p1.order can work, I find I need to do p1.order() first. How can I remove this step to make it automatic?
Here is my code, do inform me if there are any other faux pas, I'm new to classes:
class Polynomial(object):
def __init__(self,*p_coeffs):
self.p_coeffs = list(p_coeffs)
def order(self):
self.order = len(self.p_coeffs)
p1 = Polynomial(2,0,4,-1,0,6)
p2 = Polynomial(-1,3,0,4.5)
p1.order() #<-- this step is the one I want to remove so I do not need to write it for every polynomial
print(p1.order)
Thanks in advance
EDIT: I need to keep my "order" method in the process
Simply perform all instance initialization that you'd like to automatically occur within the __init__() method.
class Polynomial(object):
def __init__(self,*p_coeffs):
self.p_coeffs = list(p_coeffs)
self.set_order()
def set_order(self):
self.order = len(self.p_coeffs)
p_list = [
Polynomial(2,0,4,-1,0,6),
Polynomial(-1,3,0,4.5),
]
for p in p_list:
print(p.order)
Output:
$ python test.py
6
4

How to import global variables in python from a class module in another file?

I have a file that contains the class definitions and functions I need to use in my main file to make the text cleaner. However, I'm having a problem with imported global variables.
There is plenty of information at SO and other resources regarding how to make function variables global within the same code or how to use the global variables from an imported file. However, there is no information on how to access a variable from an imported file if the variable belongs to a function belonging to a class.
I would appreciate any help on how to do it or why it cannot be done. Please skip the lecture on the dangers of using global variables like this as my situation requires such use.
Edit: Sorry for not having an example in the original post. It's my first one. Below is an example of what I'm trying to accomplish.
Let's say I have a file classes.py that contains:
class HelixTools():
def calc_angle(v1, v2):
v1_mag = np.linalg.norm(v1)
v2_mag = np.linalg.norm(v2)
global v1_v2_dot
v1_v2_dot = np.dot(v1,v2)
return v1_v2_dot
Then in my main text file I do:
from classes import HelixTools
ht = HelixTools()
v1 = some vector
v2 = some other vector
ht.calc_angle(v1,v2)
print(v1_v2_dot)
The result is "v1_v2_dot" not defined. I need v1_v2_dot to use it as the input of another function.
Here's an example of how you can access class attributes (if I understand what it is you want to do correctly). Lets imagine you have a python file called "Test_class.py" that contains the following code:
class Foo(object):
def __init__(self, x, y):
self.x = x
self.y = y
def bar(self):
self.z = self.x + self.y
Now lets imagine you want to import this class into another python file in the same directory, and access attributes of that class. You would do this:
from Test_class import Foo
# Initialize two Foo objects
test1 = Foo(5, 6)
test2 = Foo(2, 3)
# Access the x and y attributes from the first Foo object
print(test1.x) # This will print 5
print(test1.y) # This will print 6
# Access the x and y attributes from the second Foo object
print(test2.x) # This will print 2
print(test2.y) # This will print 3
# Access the z attribute from the first Foo object
test1.bar()
print(test1.z) # This will print 11
# Access the z attribute from the second Foo object
test2.bar()
print(test2.z) # This will print 5
This works because variables defined in the __init__ magic method are initialized as soon as the Foo object is first called, so the attributes defined here can be access immediately after. The bar() method has to be called before you can access the z attribute. I made 2 Foo objects just to show the importance of including "self." in front of your variables, in that each attribute is specific to that particular class instance.
I hope that answers your question, but it would be very helpful if you provided some example code to show exactly what it is you want to do.
You should likely use a class attribute to store this value. Note that the implementation will depend on what your class HelixTools really does.
But for the example, you could use something like this:
import numpy as np
class HelixTools():
def __init__(self):
# Initialize the attribute so you'll never get an error calling it
self.v1_v2_dot = None
def calc_angle(self, v1, v2): # Pass self as first argument to this method
v1_mag = np.linalg.norm(v1)
v2_mag = np.linalg.norm(v2)
# Store the value in the attribute
self.v1_v2_dot = np.dot(v1,v2)
And then:
from classes import HelixTools
ht = HelixTools()
v1 = some vector
v2 = some other vector
ht.calc_angle(v1,v2) # This will not return anything
print(ht.v1_v2_dot) # Access the calculated value

Python declaring an array/list static and global

I am trying to learn python. I am making a small program that holds some number or string on a static array. I want my function to hold variables in a single array. But after I finished my function, the array is also gone. How can I make my array static in python? I want to change it in several functions.
py_ppl = []
def Dong():
alc1 = alc.get()
alc2 = alc1
alc1 = [0]
py_ppl.append(alc1[0])
py_ppl.append(alc2)
I mean something like this. I get alc with Tkinter Gui.
This example of using class variables may help you. Variables declared in init are local to each instance of the class and variables declared at the top of the class are global to all instances of the class.
class funkBox:
globalToBox = [] # our class variable
def __init__(self):
pass # our do nothing constructor
def funk(self,elm): # our function
self.globalToBox.append(elm)
def show(self): # for demonstration
print(self.globalToBox)
a = funkBox() #create one instance of your function holder
b = funkBox() #and another
a.funk("a") #call the function on the first instance
b.funk("b") # call the function again
a.show() # show what instance a has
b.show() # and b
Prints
['a', 'b']
['a', 'b']

Categories