10

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?

1
  • I cannot believe that I found out this fact after 4 month of learning python. :) Good question! Commented Sep 28, 2020 at 16:38

4 Answers 4

14

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)
Sign up to request clarification or add additional context in comments.

Comments

5

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

4 Comments

Yes. I noted this. But my question revolves around why self.message is not working in my question [ without using a seperate function as you just provided].
but i changed self.name rite? so self.message again should dynamically take new self.name value?
No. That's the whole point. edited my answer. the init gets initialized only one time, when you declare your class.
@syam Python just doesn't work this way. Are you thinking of a different programming language that does? The fact is, practically every mainstream programming language treats variables (and attributes) as boxes in which you put computed values which are NEVER "dynamically reassigned"! That said, Python, like other languages, gives you language mechanisms to give you exactly that appearance. In Python's case, it is @property.
2

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.

1 Comment

Thanks!!! but i changed self.name rite? so self.message again should dynamically take new self.name value? as when i print self.message now, it looks for self.name and it is the new name now.? self.message is created as part of initialization, but self.name is a variable which i changed after that nah?
1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.