pranshu vinayak
pranshu vinayak

Reputation: 133

Can a particular instance of a class make its own variables in python?

Can a particular instance make its own variable in python, if yes would it be available to other instances of the class?

for eg:

class A():
    Var1 = 10

inst1 = A()

inst1.Var1 # will be 10

but can inst1 make it's own variables like Var2 etc and will these Variables be available to other class A instances like inst2?

In other Words, is a variable, which is bound to an instance of a class, accessible to another instance of the same class?

Upvotes: 0

Views: 113

Answers (4)

Ovaflo
Ovaflo

Reputation: 694

Actually, the most common use case is for instances to have their "own" variables ("data attributes" in Python terminology) which are not shared between instances. The variables x and y below are examples of such "own" variables (every instance of class A gets its own variable x when the constructor is called, and inst1 also gets its own variable y later):

class A():
    def __init__(self):     # Constructor - called when A is instantiated
        self.x = 10         # Creates x for self only (i.e. for each instance in turn)

inst1 = A()
inst1.x = 15                # Changes x for inst1 only
inst1.y = 20                # Creates y for inst1 only
print(inst1.x, inst1.y)     # 15 20

inst2 = A()
print(inst2.x)              # 10

Upvotes: 1

Brian M. Sheldon
Brian M. Sheldon

Reputation: 695

To dynamically add attributes to a class or instance you can use setattr:

class MyClass(object):
    pass

my_instance = MyClass()


# add attribute to class
setattr(MyClass, 'new_attribute', 'added')

# Class now has attribute
print(MyClass.new_attribute == 'added')  # True

# Which is also available to instance
print(my_instance.new_attribute == 'added')  # True

# Add attribute to instance
setattr(my_instance, 'instance_only', 'yup')

# Instance now has attribute
print(my_instance.instance_only == 'yup')  # True

# Class does not have attribute
MyClass.instance_only # Raises AttributeError

# Add attribute to instances class
settatr(type(my_instance), 'instance_only', 'not anymore')

# Now the attribute is available to the class as well
print(MyClass.instance_only == 'not anymore')  # True

# New instances will also have the attributes
new_instance = MyClass()
print(new_instance.new_attribute == 'added')  # True

If you are not adding them dynamically see @gilch's answer

Upvotes: 1

gilch
gilch

Reputation: 11691

It depends on if you set the variable in the class's dict or the instance's dict.

>>> class A:
    var = 10


>>> inst1 = A()
>>> inst2 = A()
>>> inst1.var  # not in instance, so looked up in class
10
>>> inst2.var
10
>>> inst2.var = 20  # instance attr shadows that from class
>>> inst2.var
20
>>> A.var = 30  # class attr can also be altered
>>> inst1.var
30
>>> inst2.var
20
>>> del inst2.var  # deleting instance attr reveals shadowed class attr
>>> inst2.var
30
>>> inst1.var2 = 'spam'
>>> inst2.var2  # new attr was set on inst1, so not available in inst2
Traceback (most recent call last):
  File "<pyshell#663>", line 1, in <module>
    inst2.var2
AttributeError: 'A' object has no attribute 'var2'
>>> inst1.__class__.var3 = 'eggs'  # same as A.var3 = 'eggs'
>>> inst2.var3  # new attr was set on the class, so all instances see it.
'eggs'

Upvotes: 0

jbndlr
jbndlr

Reputation: 5210

Even though the actual use may be questionable, you actually can bind new attributes to a class definition in a way that they are available to all instances of that class:

class A(object):
    attrib_one = 'VALUE'

    def add_class_attrib(self, name, value):
        # Bind new attribute to class definition, **not** to self
        setattr(A, name, value)

if __name__ == '__main__':
    # Instantiate _before_ changing A's class attributes
    a = A()
    b = A()
    # Add a new class attribute using only _one_ instance
    a.add_class_attrib('attrib_two', 'OTHER')
    # Print attributes of both instances
    print([e for e in dir(a) if not e.startswith('__')])
    print([e for e in dir(b) if not e.startswith('__')])

    # Create new instance _after_ changing A's class attribs
    c = A()
    # Print attributes of new instance
    print([e for e in dir(c) if not e.startswith('__')])

Running this code will print the following:

['add_class_attrib', 'attrib_one', 'attrib_two']
['add_class_attrib', 'attrib_one', 'attrib_two']
['add_class_attrib', 'attrib_one', 'attrib_two']

And you see, that -- even if a class attribute is added to the class definition after an instance of it has been created, the newly created class attribute in fact is available to all other instances of that (changed) class.

Upvotes: 0

Related Questions