Because Python is a dynamic language, you can dynamically redefine and add methods to classes and instances at runtime.
class User:
pass
user1 = User()
user1.set_username('kaito')
Calling an undefined property or method will result in an error.
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-30-815371892d44> in <module>
3
4 user1 = User()
----> 5 user1.set_username('kaito')
AttributeError: 'User' object has no attribute 'set_username'
You can add methods later by using MethodType </ code>.
First, define the method as a function (you need to define self as an argument like a method).
def set_username(self, username):
self.username = username
Then bind the method to the instance.
from types import MethodType
user1.set_username = MethodType(set_username, user1)
user1.set_username('kaito')
user1.set_username
You can see that it is bound as a method.
<bound method set_username of <__main__.User object at 0x111f55438>>
What happens if I assign directly without using MethodType </ code>?
user1.set_username = set_username
user1.set_username
It's just a reference to a function object.
<function __main__.set_username(self, username)>
Try to run it.
user1.set_username(user1, 'kaito')
It's a function, not a method, so it doesn't assign self.
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-42-70cc4337e082> in <module>
----> 1 user1.set_username('kaito')
TypeError: set_username() missing 1 required positional argument: 'username'
It can be executed by explicitly giving self.
user1.set_username(user1, 'kaito')
What about the User class?
User.set_username
I added it only to the instance, so the class doesn't change.
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-38-40cdce039232> in <module>
----> 1 User.set_username
AttributeError: type object 'User' has no attribute 'set_username'
If you want to add a method to your class, you can do it the same way.
User.set_username = MethodType(set_username, User)
User.set_username
The memory address is not displayed like the instance, but it is added properly.
<bound method set_username of <class '__main__.User'>>