Class member variables are not treated locally [duplicate] - python

This question already has answers here:
How to avoid having class data shared among instances?
(7 answers)
Closed 9 years ago.
Look at the code below:
class Node:
feature = list()
label = list()
def __init__(self, f, l):
self.feature.append(f)
self.label.append(l)
I create two instances of this class:
n1 = Node(1,2)
print n1.feature
n2 = Node(3,4)
print n2.feature
My desired output is:
1
2
But the real output is:
1
1 2
What is the problem? How can I fix it?

variables defined in class scope are class variables, and are share among all class instances (they are stored on the class object itself, not on the instances).
Just initialize the variables inside the init function.
class Node:
def __init__(self, f, l):
self.feature = [f]
self.label = [l]

The issue is that you're trying to "declare" the member data for the class instances in the class block. That's not how Python works.
Everything defined in the class block (including feature, label, and __init__) becomes an attribute of the object that represents the class itself, not the instances of the class. Trying to access an attribute that doesn't exist in an instance will fall back to the class, which is how method lookup works.
There is no way to create a attribute on an instance until it exists and you have a reference to it. The purpose of the __init__method is to give you a place to do that. So initial values for an instance's member data should be set up in __init__; trying to declare these initial values in the class block actually does something else.

Related

Python: sharing "static" variables through inharitence [duplicate]

This question already has answers here:
Changing class attributes by reference
(1 answer)
How to change class attributes using a method?
(2 answers)
How to change a class attribute inside __init__?
(2 answers)
Closed 2 years ago.
I have a particular problem with objective python, I would like to have a configuration class (Config), so it could be used as a base class for other classes which will need configuration data. What I want do is to use this Config class to share once iniciated data among all inheriting classes. What is important for me, when class Inherit configuration data I want it to be able to use it as it owns, for ex:
class Config:
a= None
b= None
class A(Config):
def __init__(self):
a = 10
def print_a(self):
print(self.a)
And here is the first questione, how should I set values of a and b in A class? Another one is how to call them inside the class?
When I'm doing sth like this :
obj = A()
obj.a = 5
or when i add methon do A class, which sets a variable:
class A(Config):
def __init__(self):
a = 10
def print_a(self):
print(self.a)
def setA(self, val):
a = val
and call :
obj = A()
obj.setA(12)
it does not change either A.a or Config.a
To sum up, my goal is to create a class with static variables (Config), and through inheritance I would like to obtain acces to those variables from another class A(Config), and use those variables as they were native class variables. It is also important that every change in obj = A() -> obj.a should change Config.a variable (the same when I change variable a insade class A).
Its sucha a confusing idea what I want to do, hope you understand. Also I am pretty new to python so there is a lot of I dont understand yet, try to be forgiving please :).
IGNORE THIS, I MISUNDERSTOOD THE QUESTION, LEAVING OPEN FOR COMMENTS
Well as far as I can see, the problem is the lack of the use of self. In the methods A.setA() and A.__init__, you have to used self.a and thus have simply created a local variable for the method.
So a functioning version of the class A would look like this:
class A(Config):
def __init__(self):
self.a = 10 #As I mentioned, you need this `self.a` rather than just `a`
def print_a(self):
print(self.a) #You got that right
def setA(self, val):
self.a = val #Same here with `self.a`
Think of making a method as simply defining a variable of the function class, and that the method behaves the same as it would outside of a class apart from the additional self argument, which is used to access the attributes of the class.

Python - Sharing variables between different instances of different classes [duplicate]

This question already has an answer here:
Python: How to share data between instances of different classes?
(1 answer)
Closed 4 years ago.
I have been searching for the next answer but for sure I have been searching the wrong keywords.
I used to develop with C++, passing pointers as references between objects. The case is, now I'm trying to build a program in Python where one instance of a class 'General' initializes different instances of a class 'Specific' with the same shared variable.
class General():
def __init__(self):
self._shared_variable = 0
self._specific1 = Specific(self._shared_variable)
self._specific2 = Specific(self._shared_variable)
class Specific():
def __init__(self, shared):
self._shared = shared
def modify_shared_variable(self):
self._shared_variable +=1
So what I'm trying to do is shared this 'shared_variable' within de General scope, so when a 'Specific' instance modifies his internal variable, this change is seeing or mirrored by the other instance. But this is not the case in python. So, every specific instance has its own variable. How can I achieve this?
You can't have references to variables in Python. A variable is just a name, in some namespace (usually the __dict__ of a module, class, or instance object, or the special local namespace inside a function-call frame), for a value.
You can have references to values, but of course numbers are immutable values, so you can't change the number 1 into the number 2.
So, what you can do is create some kind of mutable value that holds the number, and share references to that.
One obvious possibility is to just give each Specific instance a reference to the General instance that created it:
class General():
def __init__(self):
self._shared_variable = 0
self._specific1 = Specific(self)
self._specific2 = Specific(self)
class Specific():
def __init__(self, shared_general):
self._shared_general = shared_general
def modify_shared_variable(self):
self._shared_general._shared_variable +=1
Another possibility is to store a single-element list:
class General():
def __init__(self):
self._shared_variable = [0]
self._specific1 = Specific(self._shared_variable)
self._specific2 = Specific(self._shared_variable)
class Specific():
def __init__(self, shared):
self._shared = shared
def modify_shared_variable(self):
self._shared[0] += 1
(This is really the same thing you're doing in C++, but without the syntactic sugar of arrays and pointers being nearly the same thing…)
Or you can create a simple MutableInteger class that holds an int, proxies non-mutating methods to it, adds a set method to replace it, and handles += and other mutating methods by calling set and returning self, instead of returning a new value.

Python: how to access super attribute at class level attributes definition [duplicate]

This question already has answers here:
python subclass access to class variable of parent
(2 answers)
Closed 6 years ago.
In Python, when defining a class it's possible to use previously defined attributes in new attributes definition without any further reference.
class Parent(object):
a_value = 'a'
another_value = 'b'
all_values = (a_value, another_value)
Is it possible to do the same in a derived class but still accessing some of these parent attributes?
I tried doing something like this:
class Child(Parent):
a_child_value = 'c'
all_values = (a_value, another_value, a_child_value)
But it seems that it doesn't take into account the Parent inheritance and gives me the following error:
NameError: name 'a_value' is not defined
So, is there any way to indicate that the a_value and another_value should be from the parent class instead of the current context?
In my case in particular the values are not strings but rather pre-compiled regular expressions, so I would like to avoid having to create them inside the __init__ method every time a new instance is created.
like this.
class Child(Parent):
a_child_value = 'c'
all_values = (Parent.a_value, Parent.another_value, a_child_value)
You need to do Parent.a_value in order to get the value you are after. a_child is a static attribute and therefore attached to the class itself and not a local variable.
class Child(Parent):
a_child_value = 'c'
all_values = (Parent.a_value, Parent.another_value, a_child_value)
If it is derived from something, you HAVE to type what it is derived from.

How access variables inside method? (python) [duplicate]

This question already has answers here:
Python class attribute referencing
(2 answers)
Closed 7 years ago.
Is it possible to access self.bin outside the class?
class kon():
def __init__(self):
pass
def add(self):
con=7
self.bin=100
h=kon()
bin=h.bin
In one topic advised to use self. before variables but it did not work.
Maybe such variables must be in __init__ method.
You have to read docs. It will be very useful for you.
The instantiation operation (“calling” a class object) creates an empty object. Many classes like to create objects with instances customized to a specific initial state. Therefore a class may define a special method named init(), like this:
def __init__(self):
self.bin = 0
When a class defines an init() method, class instantiation automatically invokes init() for the newly-created class instance.
After this you can use this property in you object, to read or assign value.
Also, there is a difference between initialize properties in the class. From the docs:
class Dog:
kind = 'canine' # class variable shared by all instances
def __init__(self, name):
self.name = name # instance variable unique to each instance

Python new list not created upon object creation [duplicate]

This question already has answers here:
Weird list behavior in class
(4 answers)
Closed 9 years ago.
I'm doing some practicing with OOP in python and I've run into an issue that my non-computer scientist mind cannot comprehend. I'm sure it's just due to my inexperience with OO but I can't seem to find an answer for it anywhere.
So I've got three classes. A class called tester, which should contain a unique object called group, which should contain a list of objects called atom. My issue is that whenever I create multiple groups they all seem to have the same list object. So whenever I append an atom to the list it gets appended to all the group's lists. My code is:
count = 0
testers = []
class atom:
def __init__(self):
pass
class group:
myList = list()
def __init__(self):
pass
def createAtom(self):
self.myList.append(atom())
class tester:
def __init__(self):
self.myGroup = group()
for k in range(4):
testers.append(tester())
print testers[k].myGroup
for t in testers:
t.myGroup.createAtom()
print t.myGroup.myList
I would expect this to create a new list for each group and that this would add a single atom to each group. This instead creates an output as follows.
<__main__.group instance at 0x02C2E058>
<__main__.group instance at 0x02C2E0A8>
<__main__.group instance at 0x02C2E0F8>
<__main__.group instance at 0x02C2E148>
[<__main__.atom instance at 0x02C2E170>]
[<__main__.atom instance at 0x02C2E170>, <__main__.atom instance at 0x02C2E198>]
[<__main__.atom instance at 0x02C2E170>, <__main__.atom instance at 0x02C2E198>, <__main__.atom instance at 0x02C2E1C0>]
[<__main__.atom instance at 0x02C2E170>, <__main__.atom instance at 0x02C2E198>, <__main__.atom instance at 0x02C2E1C0>, <__main__.atom instance at 0x02C2E1E8>]
A single list gets all four atoms. I apologize for my likely poor code. If it's of any help, I'm using python portable 2.7.5.1. Any insight into this would be greatly appreciated.
Thanks
Your list is a class attribute, shared amongst all instances:
class group:
myList = [] # class attribute
def __init__(self):
pass
Instead, make it an instance attribute, separate for each instance of the class:
class group:
def __init__(self):
self.myList = [] # instance attribute
Note that I have replaced list() with [], per thefourtheye's comment. It is bad practice to shadow built-ins (e.g. having your own list or other object named list), but this avoids side effects if the rule gets broken.
You've made group.myList a class attribute, shared by all instances.
class group:
#myList = list() # <--- this defines a 'class' attribute
# which is shared by all instances of 'group'
def __init__(self):
self.myList = list() # <--- do this instead to create an instance attribute
def createAtom(self):
self.myList.append(atom())
Move the mylist = list() in class group into the __init__ of class group.
Doing so would make group create a new list every time a new group instance is created. Otherwise, all you've done is create a class-level variable (not instance-level), which will be shared among all instances of the same class.
Think of class variables as sort of a "hive mind" (think of The Borg from Star Trek) structure for all instances of that class. Any changes made to a class variable will be visible to all objects of that type.
On the other hand, if you were to create an instance variable (a variable initialized in __init__), then each instance would have its own value for that variable. Thus any changes that one instance makes to its variable will be invisible to other instances of the same type

Categories