Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

python

oop

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?

like image 358
syam Avatar asked Dec 30 '17 08:12

syam


People also ask

Can class attributes be changed in Python?

But be careful, if you want to change a class attribute, you have to do it with the notation ClassName. AttributeName. Otherwise, you will create a new instance variable.

How do you check attributes of an object in Python?

To check if an object in python has a given attribute, we can use the hasattr() function. The function accepts the object's name as the first argument 'object' and the name of the attribute as the second argument 'name. ' It returns a boolean value as the function output.


4 Answers

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)
like image 130
Ray Toal Avatar answered Oct 21 '22 01:10

Ray Toal


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
like image 40
sheldonzy Avatar answered Oct 21 '22 00:10

sheldonzy


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.
like image 34
Laurent LAPORTE Avatar answered Oct 21 '22 00:10

Laurent LAPORTE


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.

like image 40
Muku Avatar answered Oct 20 '22 23:10

Muku