Indradhanush Gupta
Indradhanush Gupta

Reputation: 4237

How to use a variable within a class that will be independent of any objects created in python?

I want to use a variable that will be independent of any objects the class may have :

    class A:
        var = 5
    ob1 = A()
    ob2 = A()
    ob1.var += 2
    print ob2.var

I want that once ob1 modifies the value of var from 5 to 7, ob2.var also shows up 7 instead of 5. How do I do this?

Upvotes: 2

Views: 116

Answers (3)

mgilson
mgilson

Reputation: 310227

I suppose you could use a property to do something like this:

class Foo(object):
    _var = 5

    @property
    def var(self):
        return self._var

    @var.setter
    def var(self,value):
        self.__class__._var = value

a = Foo()
b = Foo()

a.var += 3
assert a.var == 8
assert b.var == 8

c = Foo()
assert c.var == 8 #(un-instantiated objects pick up the change as well)

class Bar(Foo):
    pass

bar = Bar()
assert bar.var == 8
a.var += 1

#changes to Foo.var affect Bar until a bar object makes it's own changes
assert bar.var == 9    

# changes to a subclass's property don't have any effect on the parent class
bar.var += 2
assert bar.var == 11
assert a.var == 9

As noted in the comments, this could get a little tedious if you have a lot of properties which behave this way. A slightly more general solution would be to do something like:

class ClassAttribute(object):
    def __init__(self,vname,default=None):
        self.vname = '_'+str(vname)
        self.default = default

    def __get__(self,instance,owner):
        return getattr(owner,self.vname,self.default)

    def __set__(self,instance,value):
        setattr(instance.__class__,self.vname,value)

class Foo(object):
    var = ClassAttribute("var",5)

a = Foo()
b = Foo()
a.var += 2
print a.var
print b.var

Upvotes: 2

Andrew Clark
Andrew Clark

Reputation: 208665

When you do ob1.var += 2 you are not modifying the class attribute, you are creating a new instance variable with the same name as the class attribute. For example:

>>> ob1 = A()
>>> ob1.var += 2
>>> ob1.__dict__
{'var': 7}
>>> ob1.__class__.__dict__
{'var': 5, '__module__': '__main__', '__doc__': None}

If you want to modify the class attribute, just use A.var += 2. If you need to do this from an instance you can use ob1.__class__.var += 2.

Here is how you could implement the behavior you want using properties on a new-style class:

class A(object):
    _var = 5

    @property
    def var(self):
        return self.__class__._var

    @var.setter
    def var(self, value):
        self.__class__._var = value

Now with this class when you get or set the var variable on an instance of A, it will actually be getting or setting a class attribute. For example:

>>> ob1 = A()
>>> ob2 = A()
>>> ob1.var += 2
>>> ob2.var
7

Upvotes: 5

Joran Beasley
Joran Beasley

Reputation: 114088

you are already close

class MyData:
    my_data_var = 4

class A:
    def fun1():
       MyData.my_data_var += 2

    def fun2():
       return MyData.my_data_var

def main():
    print MyData.my_data_var 
    a = A()
    a.fun1()    
    print a.fun2()
    b = A()
    b.fun1()
    print b.fun2()
    print a.fun1()

main()

these are static class variables ... there are other ways to simillarly utilize them ... but this was a simple quick example

Upvotes: 2

Related Questions