Inside __init__, use variable from outside __init__ - python

After reading this answer, I understand that variables outside of __init__ are shared by all instances of the class, and variables inside __init__ are unique for every instance.
I would like to use the variables that are shared by all instances, to randomly give my instance of the class a unique parameter. This is a shorter version of what I've tried;
from random import choice
class Chromosome(object):
variable1 = [x for x in range(1,51)]
variable2 = [x for x in range(51,101)]
def __init__(self):
self.var1 = choice(variable1)
self.var2 = choice(variable2)
My problem is that I can't reach the instance variables when initializing a new instance, the error message says name "variable1" is not defined, is there anyway to get around this?
EDIT: The reason I want to create the lists outside of the __init__ is to save memory, if I create 10.000 chromosomes with around 10-15 variables each, then it's better if I just create the lists once, instead of creating them for every chromosome.
EDIT2: If anyone wants to use it, my final solution involved using random.randrange(a,b+1,2). This picks out a random number (only even numbers) in the range [a,b], including the boundaries.

You just need to use the class name when referencing it. saying variable1 to Python will make it find a variable from the scope. However, your variable is an attribute of a class.
from random import choice
class Chromosome(object):
variable1 = [x for x in range(1,51)]
variable2 = [x for x in range(51,101)]
def __init__(self):
self.var1 = choice(Chromosome.variable1)
self.var2 = choice(Chromosome.variable2)
Equally, you could use self.variable1 since it is just an instance of the class and will have access to the class attributes too.
The main idea here is that when you access any attributes or methods of a class, you must provide an object which has access to these methods, be it the class, a subclass or an instance of either. You wouldn’t call dict.from_keys() as from_keys(), would you?

You could also just use self instead of Chromosome. Also object is not necessary I guess.
from random import choice
class Chromosome():
variable1 = [x for x in range(1,51)]
variable2 = [x for x in range(51,101)]
def __init__(self):
self.var1 = choice(self.variable1)
self.var2 = choice(self.variable2)

Here's another way: (the above answers are all true)
import random
class Chromosome(object):
def __init__(self):
self.var1 = random.choice([x for x in range(1, 51)])
self.var2 = random.choice([x for x in range(51, 101)])

Related

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']

Python: How to make variables consistent throughout different functions?

I'm still starting out how to program in Python, and I'm just wondering how to make a variable consistent throughout different functions. For example, a function that I've made modified a variable. Then, I've used that variable again in another function. How can I make the modified variable appear in the 2nd function? When I try it, the 2nd function uses the original value of the variable. How can you make it use the modified value? Do I need to use global variables for this?
Also, is the input() function recommended to be used inside functions? are there any side effects of using it inside them?
The variables need to be shared by a scope that is common to both functions, but this need not necessarily be a global scope. You could, for instance, put them in a class:
class MyClass:
def __init__(self):
self.x = 10
def inc(self):
self.x += 1
def dec(self):
self.x -= 1
mc = MyClass()
print mc.x # 10
mc.inc()
print mc.x # 11
mc.dec()
print mc.x # 10
What scope exactly the variable should exist in depends on what you're trying to do, which isn't clear from your question.
Use global variabale to access variable throughout code.
Demo:
>>> a = 10
>>> def test():
... global a
... a = a + 2
...
>>> print a
10
>>> test()
>>> print a
12
>>>
In class, use class variable which is access to all instance of that class. OR use instance variable which is access to Only respective instance of the class.
You can use return in the function.
x = 3
def change1():
x = 5
return x
x = change1()
def change2():
print(x)
change1()
change2()
You can use the global keyword at the top of the function to let python know that you are trying to modify the variable in global score. Alternatively, you could use OOP and classes to maintain an instance variable throughout class functions.
x = 5
def modify():
global x
x = 3
modify()

What is the proper way to share a list between class instances?

I have this example code
my_list = ["a","b","c","d"]
class A:
def __repr__(self):
return ', '.join(my_list)
def add(self, num):
my_list.append(num)
class_list = []
for x in range(5):
class_list.append(A())
class_list[x].add("class_%s" % (x))
print class_list[x]
The non-example code of mine is more complicated, but the idea is that I have multiple instances of the classes off doing a "thing". The global my_list is utilized across all instances. When certain logic is met within a class, that instance will modify the list. The rest of the classes will utilize that list to perform their logic as well. Any instance can add to the list, and all instances should be able to utilize the updated value.
Now in this example, the my_list is shared, but is this the correct way to do it?
A class attribute is usually better than a global, because then they're just sharing it with each other, rather than with everyone in the world.
To do that, move the my_list = ["a","b","c","d"] line under the class A:, and change every reference to my_list to self.my_list or A.my_list:
class A(object):
shared_list = []
def add(self, num):
self.my_list.append(num)
However, an instance attribute is often even better. If you assign the same list to a bunch of different variables, it's still just one list; changing it affects all those variables. So, you can do something like this:
class A(object):
def __init__(self, shared_list):
self.shared_list = shared_list
def add(self, num):
self.shared_list.append(num)
Now it's up to the code that uses the A objects to decide whether to give them all the same list. You can even create 20 instances that share one list, and 10 that share a different one:
list1 = []
group1 = [A(list1) for _ in range(20)
list2 = []
group2 = [A(list2) for _ in range(10)
The question is whether the caller, or the A class, or nobody at all is the one who should be making the decision of how "shared" the list is. The answer is different for different applications, so it's hard to give an answer for an abstract example with names like A and my_list.

Class assigning index to object using static class variable

I have a class which represents an object to be kept in a set. I would like the class itself to remember how many it has created so that when you call SetObject() and __init__() a new object is created, which receives a unique index. Maybe something like this
class SetObject(object):
# static class variable
object_counter = 0
def __init__(self, params):
self.params=params
self.index = self.get_index()
def get_index(self):
object_counter += 1
return object_counter-1
a = SetObject(paramsa)
b = SetObject(paramsb)
print a.index
print b.index
would produce
0
1
or something like this. Currently it seems that this approach gives a "variable referenced before assignment" error.
You need to write:
def get_index(self):
SetObject.object_counter += 1
return SetObject.object_counter-1
otherwise it would only work if object_counter was a global variable.
You need to use a reference to the class to refer to it's variables; you could perhaps use a class method (with the #classmethod decorator), but there is really no need to.
Better use itertools.count() to get a fool-proof 'static' counter; no need to reassign back to the class attribute then:
import itertools
class SetObject(object):
object_counter = itertools.count().next
def __init__(self, params):
self.params=params
self.index = self.object_counter()
(code above assumes Python 2; on Python 3 iterables do not have a .next method and you'd need to use functools.partial(next, itertools.count()) instead).
Because the counter is an iterator, we don't need to assign to SetObject.object_counter at all. Subclasses can provide their own counter as needed, or re-use the parent class counter.
The line
object_counter += 1
translates to
object_counter = object_counter + 1
When you assign to a variable inside a scope (e.g. inside a function), Python assumes you wanted to create a new local variable. So it marks object_counter as being local, which means that when you try to get its value (to add one) you get a "not defined" error.
To fix it, tell Python where to look up object_counter. In general you can use the global or nonlocal keywords for this, but in your case you just want to look it up on the class:
self.__class__.object_counter += 1

Categories