syam
syam

Reputation: 397

updated object's attribute in python class, but not getting reflected

consider my simple class

class stud():
    def __init__(self,a,b):
        self.name=a
        self.mark=b
        self.message=self.name + ' ' +str(self.mark)

s1=stud('student1',40)
print s1.message  --->output=student1 40 
s1.name='student2'
print s1.message ----> output =student1 40 , but i expected student2 40

My question here is why when I printed the self.message [after modifying the name attribute of the object], it printed the old value? I know init method is called only once during object creation and name attribute is set to value 'student1' at that time. But, i am changing it next line and again printing of self.message shouldn't list the new value?

Why is this self.message is not updating the modified value?

Upvotes: 10

Views: 5696

Answers (4)

sheldonzy
sheldonzy

Reputation: 5941

That is because you initialize the self.message in the init, and when you did s1.name = student2, you only changed the self.name, while the self.message was already initialized.

If you want to get the self.message, you want to update its values somehow.

what will work:

class stud():
    def __init__(self,a,b):
        self.name=a
        self.mark=b

    def the_message(self):
        self.message = self.name + ' ' + str(self.mark)
        return self.message

s1 = stud('student1',40)
print s1.the_message() 

s1.name='student2'
print s1.the_message() 

output:

student1 40
student2 40

Upvotes: 5

Laurent LAPORTE
Laurent LAPORTE

Reputation: 22942

When you call the constructor, it initializes name, mark and message.

If you modify name, you don’t call the constructor, so the message is not updated.

This statement is not called again:

self.message=self.name + ' ' +str(self.mark)

To do that, you need a function or a property to calculate the message each time you need it.

    def get_message(self):
        return self.name + ' ' + str(self.mark)


s1 = Stud('student1', 40)
print(s1.message)
s1.name = 'student2'
print(s1.get_message())

To use a property, you need to inherit from object (because this functionality is only available with the new style class in Python 2).

You can do that:

class Stud(object):
    def __init__(self, a, b):
        self.name = a
        self.mark = b

    @property
    def message(self):
        return self.name + ' ' + str(self.mark)

s1 = Stud('student1', 40)
print(s1.message)
s1.name = 'student2'
print(s1.message)

Note on code style:

  • class names should be in CamelCase,
  • variable and function names should be in snake_case.

Upvotes: 2

Ray Toal
Ray Toal

Reputation: 88378

Trace the execution.

s1=stud('student1',40)

This sets

  • s1.name to "student1"
  • s1.mark to 40
  • s1.message to "student1 40"

Think of the attribute values as boxes. Each of the three boxes have a value in them. Two of them hold strings. One of them holds a number. They will hold those values until they are explicitly assigned to. In particular the attribute message has NO IDEA how it got its value. It has no idea it got its value by concatenating the name attribute and the mark attribute. All it knows is that the value it has is "student1 40".

print s1.message

This outputs student1 40 (no surprise)

s1.name='student2'

You updated one of the three attributes. But you did not update the others.

print s1.message

Since you never explicitly changed s1.message, this still outputs student1 40.

The point is the value of s1.message is just a string. There is no invisible computation that automatically updates it whenever the expression that initialized it gets changed. Other languages work that way perhaps, but Python does not.

If you want that behavior, then do this:

class stud():
    def __init__(self,a,b):
        self.name=a
        self.mark=b

    @property
    def message():
        return self.name + ' ' +str(self.mark)

Upvotes: 14

Muku
Muku

Reputation: 562

Because you have only changed the name attribute not the message so its still printing the same message.

What you need is define your message as an function rather than an attribute. Go ahead and try it.

Upvotes: 1

Related Questions