FAQ: Learn Python: Inheritance and Polymorphism - Overriding Methods

This community-built FAQ covers the “Overriding Methods” exercise from the lesson “Learn Python: Inheritance and Polymorphism”.

Paths and Courses
This exercise can be found in the following Codecademy content:

Computer Science

FAQs on the exercise Overriding Methods

Join the Discussion. Help a fellow learner on their journey.

Ask or answer a question about this exercise by clicking reply (reply) below!

Agree with a comment or answer? Like (like) to up-vote the contribution!

Need broader help or resources? Head here.

Looking for motivation to keep learning? Join our wider discussions.

Learn more about how to use this guide.

Found a bug? Report it!

Have a question about your account or billing? Reach out to our customer support team!

None of the above? Find out where to ask other questions here!

19 posts were split to a new topic: How does edit_message know to reference the Message class?

5 posts were split to a new topic: Can variable definitions be done right to left?

Why does the Admin class need message.text = new_text? Shouldn’t the class just inherit everything from the User class?

class Message:
  def __init__(self, sender, recipient, text):
    self.sender = sender
    self.recipient = recipient
    self.text = text

class User:
  def __init__(self, username):
    self.username = username
    
  def edit_message(self, message, new_text):
    if message.sender == self.username:
      message.text = new_text
      
class Admin(User):
  def edit_message(self, message, new_text):
    message.text = new_text```

you will inherit parent methods, but sometimes you want to overwrite parent methods, which is what you do in Admin class.

Because admins should be able to edit any message, not just there own. Users can only edit there own messages.

Thanks! That’s much clearer now.

it was suggested to call every method to see how it works. So not understanding why I am recieving this error :
Traceback (most recent call last):
File “script.py”, line 19, in
gayleuser.edit_message(‘message’,‘new_text’)
File “script.py”, line 12, in edit_message
if message.sender == self.username:
AttributeError: ‘str’ object has no attribute ‘sender’

for the code below in which I am calling the edit message method

class Message:
  def __init__(self, sender, recipient, text):
    self.sender = sender
    self.recipient = recipient
    self.text = text

class User:
  def __init__(self, username):
    self.username = username
    
  def edit_message(self, message, new_text):
    if message.sender == self.username:
      message.text = new_text
class Admin(User):
  def edit_message(self,message,new_text):
    message.text = new_text
gaylemsg = Message('gj','ak','what the ■■■■')
gayleuser = User('gaylejames')
gayleuser.edit_message('message','new_text')

string ('message) has no attribute sender (if message.sender).

The message parameter of your edit_message method expects a instance of the Message class. Which you currently do not provide.

oh ok thanks , got that now . And if i wish to display/print from the edit_message I have to use ‘return’ correct?

return has nothing to do with showing something on a screen
If you consider a hello world program, a program that prints “hello world” and exits, what does that do to make something show up on screen? You’d do the same thing.

i mean return and then print it out.

But is there a meaningful value that edit_message can return?
I suppose it could return a boolean to indicate success, or the message regardless of whether it was updated - but I don’t like it when functions/methods both have an effect and return something because then it becomes unclear what its purpose is, it becomes possible to use it for one thing and have an unwanted side-effect… it should do one thing.

If you mean that you want to read the message after editing it, then you could edit it, and then read it.

oh ok so methods/function should do one thing in your opinion. thanks for the insight. :slightly_smiling_face:thanks everyone

As an extreme example, you could have a function that waters the dog, walks the cactus, bakes the spaghetti, and pets the neighbour.

But if you only want to do one of those things, you’d have a hard time isolating only that behaviour. That function is doing too many things.

And if you use that function, it won’t be clear which of those things you actually want, or it might look like only one things is being done, when there are many things being done.

So yes, functions/methods are units for doing a single thing.
You can use them together to get more complicated actions, they compose quite well.

awesome thanks for elaborating! :grinning:

Hi there :slight_smile:
My question concerns this line in the User class in the edit_message method definition:
if message.sender == self.username:
Namely - how can we compare an instance of the User class (message.sender) to basically a name of one stored in variable (self.username)?
I stuck with this issue and every time I want to move forward with the lesson, it comes back to me. :slight_smile:

The sender should be an email address, not a whole user object.

1 Like

I have spent couple of days to get somewhere in this.

Here is the code:

class Message:
  def __init__(self, sender, recipient, text):
    self.sender = sender
    self.recipient = recipient
    self.text = text

class User:
  def __init__(self, username):
    self.username = username
    
  def edit_message(self, message, new_text):
    if message.sender == self.username:
      message.text = new_text

class Admin(User):
  def edit_message(self, message, new_text):
    message.text = new_text

test_text = 'This is test message!'             #define text for first message
test_text_002 = 'This is second test message!'  #define text for second message
edited_text = 'This is edited text'             #define text for edited message
user_001 = User('[email protected]')      #define sender
user_002 = User('[email protected]')      #define recipient
admin = Admin('admin')                          #define admin
first_message = Message(user_001,user_002,test_text)          #create first message 
second_message = Message('[email protected]','[email protected]',test_text_002) #create second message 

Question #1:
Which is the right format for message in case of original code? first_message or second_message? Or third option? If there is no third option please proceed to question #2.

Question #2:

Is the original code even suppose to work?

If so, I kindly ask to provide code where author can edit his message.

Deep breath…

As in case of first_message, method of .edit_message will never be used, because to edit you have to take User class object (user_001), use .edit_message method, with parameters in parentheses first_message (Message class) and edited_text (string) :

user_001.edit_message(first_message,edited_text)

As an outcome we get never True objective to fulfill:

if message.sender == self.username

Because:
message.sender is object type (unless you change to message.sender.username)
self.username is username of the user that tries to edit message

Deep breath…

In case of second_message there is a Message class object, that uses self.sender and self.recipient as strings. So as it was mentioned in many answers “you cant use any method (like .edit_message) on a string”. And Message class object has no .edit_message method. So there is no way to edit the message.

You can’t use this:

'[email protected]'.edit_message(second_message,edited_text)

Because string has no class.

To edit you have to define new user that will use User class

user_003 = User('[email protected]')

Then you can edit the message with

user_003.edit_message(second_message,edited_text)

Doing this by hand doesn’t make much sense, so there must be some method implemented inside Message class, to create usernames (User class) from strings. Which from other hand, also don’t make much sense, because we still bump into problem of the first_message:

if message.sender == self.username

Or sense is circular :rofl:

Deep breath…

So anyway…
In both cases of messages the only user that can edit a message is user that is from Admin class. Or am I missing something…

2 Likes

The exercise seems to go for second message approach. Which is possible, you still need user objects but then only pass the username to the message method

Message(user_001.username, user_002.username, test_text)

This prevents unnecessary data in the method maybe?

If you want to go for the first approach, you would need to make a change to the edit message method

Second message means that this:

Message('[email protected]','[email protected]',test_text_002)

will have same configuration as this:

That will look like:

class ( string, string, string )

As a result Message class object is created, that cannot be edited unless Admin class does it. As there is no User defined for this Message. So to edit Message, username must be predefined, created inside Message class from Message itself, or created after creating message(s) outside of any class method. Right? :slight_smile:

Too complicated question for me yet even if it is rhetorical. From point of view of the beginner (me), it is more efficient to add .username inside of .edit_message like this:

if message.sender.username == self.username

Afterwards make sure that every message contains User class object, and there will be no need to type .username for every message, in case of code reuse.

Well that is where the main question raises, I guess:
Is it better to have extra piece of code for every Message, so as a result every message will carry string information within?
Or is it better for Message to carry object information of User within?

As I see it - every symbol uses some space, so for reduce usage of space, might be better adding peace of code once.
From other hand if object carries additional object inside, that might have impact on performance while reading it, as hardware will have to unpack object attributes every time.

Is this somewhere close to developing, or the question raised is from different field, and it is only a matter of approach while coding?