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

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.

Related

How to properly access and set class variables in a derived class?

Supposed that you have a python class (say B) that is a derived class of some other class (say A) and that class A has both class variables and #classmethods that help you change or view these class variables. I had assumed that a #classmethod in class A that sets a class A class variable using the syntax cls.variable_name = value would work.
This seems to work sometimes but not always which confuses me. Below is an example that does not set the class variables as I would expect. Therefore I cannot tell what cls.something will be accessing and so I have to use A.something which seems that I will be missing the capabilities of cls.something in #classmethods. What does cls.something actually access in class methods and why does the following example not set the test class class variables?
The following example with output hopefully demonstrates what I mean:
class Test():
epf = 'A'
#classmethod
def set_formats(cls, p):
cls.epf = p
#classmethod
def form(cls):
return cls.epf
class Mytest(Test):
pass
Here is the output:
>>>c=Mytest
>>>Test.form()
'A'
>>>c.set_formats(p='a')
>>>Test.epf
'A'
>>>c.form()
'a'
>>>c.epf
'a'
So in this example the classmethods are not changing the class variable as I would expect and instead an instance variable seems to appear. If I do the above without a derived class then it works as expected. Hmm? Clearly missing something here!
Now if I change the c.set_formats(p='a', f='A') to Test.set_formats(p='a', f='A') it does work. Is it because c.set_formats uses the class method with cls being an instance?
Edit: Made the code much smaller and changed conventions as requested.
Is it because c.set_formats uses the class method with cls being an instance?
Yes, you can check via print calls showing the ids of the involved objects.

Can I access a class variable using object of that class

I have two very basic object oriented question
1) Can we modify a class variable with member function?
For example
class test:
'''test class'''
idd=0
def __init__(self,mark,subject):
self.markk=mark
self.subjectt=subject
def display(self):
print "the display is",self.markk,self.subjectt;
stud1=test(30,'maths')
stud2=test(40,'english')
when i tried to modify class variable idd using the object stud1.idd=9;, the variable didnt modified. test.idd=9 modified the variable.
Can someone explain me why it is not possible to modify a class vars from a object?
2) Also in the above snippet, when I added a keyword global with the class var idd like
class test:
'''test class'''
global idd;
idd=0;
print test.idd
it threw error like name class test don't have attribute idd.
But when I commented out the global idd, it displayed value.
So is global keyword not supported in class?
can someone help me to get some idea on these two question as this is my basic step to object oriented concept..
I think that you're not understanding that python looks up values by looking at a "chain" of objects1. When you do value = self.foo, python will first look for foo on the instance. Then it will look on the class. Then it will look on the super-classes (in their "Method Resolution Order").
When you write:
self.foo = 'bar'
Python simply puts a foo on the instance. So now subsequent lookups on that instance will give you 'bar' even if foo is also defined on the class. Also note that since foo gets put on the instance, no changes are visible on the class.
If you want to update the class in a particular method, you might be able to use a classmethod:
class Foo(object):
idd = 0
#classmethod
def increment_idd(cls):
cls.idd += 1
f = Foo()
f.increment_idd()
print(Foo.idd)
print(f.idd)
This doesn't work if you need access to self however. In that case, you'll need to get a reference to the class from the instance:
class Foo(object):
idd = 0
def increment_idd(self):
cls = type(self)
cls.idd += 1
f = Foo()
f.increment_idd()
print(Foo.idd)
print(f.idd)
1If you know javascript, it's actually not too much different than javascript's prototypical inheritance
As long as it is a public variable you should be able to.

Is it possible to implicitly assign attributes to a class, from an inherited class? [duplicate]

This question already has answers here:
How do I call a parent class's method from a child class in Python?
(16 answers)
Closed 6 years ago.
I have been unable to find any questions on this or maybe I am using the wrong nomenclature in my search. If I have something like:
class testone(object):
def __init__(self):
self.attone = None
self.atttwo = None
self.attthree = None
class testtwo(testone):
def __init__(self):
self.attfour = None
And I do:
a = test()
print dir(a)
b = testtwo()
print dir(b)
One can see that a will have all of it's attributes defined as None but b will only have attfour defined even though it inherited class testone. I understand this, but is it possible to make b have all of the attributes inherited from a implicitly defined as well at instantiation ?
I ask b/c I have classes that have tens of attributes that are inheriting from classes with hundreds of attributes and I need every attribute to be defined even if it is of type None so that I don't have to worry about checking if the attribute exists before mapping it from my object to a database table. I am trying not to write as much code. If there is a way to do this then I save well over a thousand lines of code in my class definitions or I could just verify if each attribute exists before mapping the object to my table but that's a lot of code as well as I have a couple thousand attributes to check.
Yes, but since you have overridden __init__ in the derived class, you will have to explicitly init the next class in the mro (a parent or sibling class).
class testone(object):
def __init__(self):
self.attone = None
self.atttwo = None
self.attthree = None
class testtwo(testone):
def __init__(self):
self.attfour = None
super(testtwo, self).__init__() # on python3 just use super()
For more details on inheritance, read the docs on super.
Note: I assumed you have meant for testtwo to inherit testone in your question, and have made that correction.
Since you overrode testone.__init__ you will have to call the super() function in testtwo. Another thing you can do is take the __init__ variables
class testone(object):
attone = None
atttwo = None
attthree = None
class testtwo(testone):
attfour = None

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

Class member variables are not treated locally [duplicate]

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.

Categories