Reputation: 397
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
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
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:
Upvotes: 2
Reputation: 88378
Trace the execution.
s1=stud('student1',40)
This sets
s1.name
to "student1"
s1.mark
to 40s1.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
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