Bind methods to Python classes and instances

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'>>

Recommended Posts