Bound and unbound methods of python classes

Posted by kgahn on Tue, 08 Mar 2022 21:14:23 +0100

1, Binding method

1. Object binding method

First, let's make it clear that all methods or functions in a class are bound to objects by default. Next, we will slowly analyze the application of binding methods through examples.

class People:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def talk(self):
        pass
    
p = People('xiaohua',18)
print(p.talk)

Output result:
<bound method People.talk of <__main__.People object at 0x000000F802C69358>>

From the above output results, the methods in the talk() class are bound to objects. Next, I'm looking at another situation.

class People:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def talk():
        pass

p = People('xiaohua',18)
print(p.talk)

Output result:
<bound method People.talk of <__main__.People object at 0x000000FF68F39358>>

Now, we remove the argument of the talk() function, and the result is the same as above. This shows that both methods in the class and functions in the class are bound to objects by default. One advantage of binding to objects is that you don't have to pass objects in manually. Objects are automatically passed to classes. If you don't believe it, let's take a look at the following examples:

'''
Did anyone answer the question? Xiaobian created a Python exchange of learning QQ Group: 531509025
 Look for like-minded partners to help each other,There are also good videos and tutorials in the group PDF e-book!
'''
class People:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def talk():
        pass

p = People('xiaohua',18)
print(People.talk)
print(p.talk)

Output result:
<function People.talk at 0x000000C54E3D0A60>  #Use only as a function call
<bound method People.talk of <__main__.People object at 0x000000C54E249358>>  #Object is called as binding method

As explained above, if a class calls a method in a class, the method is only a function. Since it is a function, it will not have the function of automatic value transfer. Take a look at the following code:

class People:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def talk(self):
        pass

p = People('xiaohua',18)
People.talk() 1
p.talk() 2

#Error reported at code 1
talk() missing 1 required positional argument: 'self'
#Normal at code 2

From the above output results, when the class calls the method in the class, i, the value will not be transferred automatically. That is to say, if the function has several parameters, we have to pass in several parameters. If you want the result to run normally, pass in all the parameters when the class name calls talk(). Namely:

People.talk(312312)

This parameter can be arbitrary, but it must be passed in. However, when an object calls a method in a class, it does not need to be passed, as shown in 2 above. Now that we know the difference, let's take a look at the following code:

class People:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def talk():
        pass

p = People('xiaohua',18)
People.talk() 1
p.talk() 2

# 1 normal execution
# 2 error reports
talk() takes 0 positional arguments but 1 was given

From the output results, when People call the talk() method, there is no need to pass parameters; When an object calls talk(), the object will automatically pass in the object as the first parameter because it calls its own binding method. Therefore, when the talk() method in the class does not take a parameter, and you pass one to it, it will obviously report an error.

To sum up, we can draw the following conclusions:

  • All methods and functions in a class are bound to objects for use;

  • Binding methods have the function of automatic value transfer. The value passed in is the object itself.

  • If a class wants to call a bound method, it must follow the parameter rules of the function. If there are several parameters, it must pass several parameters.

Smart you may ask, since the methods in the class are bound to the object, is there any method bound to the class?

The answer is, of course!

2. Binding method of class

Since the methods in the class are bound to the object by default, we should take some measures to remove the object binding relationship of the bound methods in the class and then bind them to the class.

In python, the @ classmethod method method is introduced to bind the methods in the class to the class. Let's look at the code:

'''
No one answers any questions? Xiaobian created a Python exchange of learning QQ Group: 531509025
 Look for like-minded partners to help each other,There are also good videos and tutorials in the group PDF e-book!
'''
class People:
    @classmethod
    def talk(cls):
        pass

p = People()
print(People.talk)

#Output results
<bound method People.talk of <class '__main__.People'>>

From the above results, we can see that we have added a decorator to bind the methods bound to objects in the class to the class. We have previously analyzed that if a method is bound to someone, the caller will be automatically passed to the function as the first parameter when calling the function. However, the method bound to a class is a little different from the method bound to an object:

class People:
    def __init__(self,name):
        self.name = name

    @classmethod
    def talk(cls):
        pass

p = People('xiaohua')
print(People.talk)
print(p.talk)

#Output results
<bound method People.talk of <class '__main__.People'>>
<bound method People.talk of <class '__main__.People'>>

In other words, when the object calls the binding method of the class, it will also pass the class as a parameter by default! Therefore, the following execution is normal, and the error will not be reported because this method is bound to the class and the object call does not pass parameters!

class People:
    @classmethod
    def talk(cls):
        pass

p = People()
People.talk()
p.talk()

However, if talk() has no parameters, the following code will report an error.

'''
No one answers any questions? Xiaobian created a Python exchange of learning QQ Group: 531509025
 Look for like-minded partners to help each other,There are also good videos and tutorials in the group PDF e-book!
'''
class People:
    @classmethod
    def talk():
        pass

p = People()
People.talk()
p.talk()
#Error reporting result
talk() takes 0 positional arguments but 1 was given

The error results of the two are consistent, which shows that when the object calls the binding method of the class, the class is automatically passed in, and the rules of function parameter transfer do not need to be followed.

There are basically two binding methods in the class. No matter how they change, just remember the following rules. In this case, you will not be wrong again.

The methods in the class are bound to the object by default. When the object calls the bound method, the object will be automatically passed in as the first parameter; Class to call, you must follow the rule of one-to-one correspondence of function parameters. If there are several parameters, you must pass several parameters. If a method uses the @ classmethod decorator, the method is bound to the class. Whether it is called by object or class, the class will be passed in as the first parameter.

2, Unbound method

As mentioned above, methods in a class are either bound to objects or classes. Is there a function that is not bound to both?

Answer: of course, python provides us with @ staticmethod, which can break the binding relationship and turn the method in a class into an ordinary function.

Let's take a look at the code example:

import hashlib
import time
class MySQL:
    def __init__(self,host,port):
        self.id=self.create_id()
        self.host=host
        self.port=port
    @staticmethod
    def create_id(): #It's just an ordinary tool
        m=hashlib.md5(str(time.clock()).encode('utf-8'))
        return m.hexdigest()


print(MySQL.create_id) #<function MySQL.create_id at 0x0000000001E6B9D8> #The view result is a normal function
conn=MySQL('127.0.0.1',3306)
print(conn.create_id) #<function MySQL.create_id at 0x00000000026FB9D8> #The view result is a normal function

From the above output results, we can see that @ staticmethod is used to decorate a function, which is no different from ordinary functions. Since it is an ordinary function, it follows the function parameter transfer rules. If there are several parameters, pass several parameters.

Topics: Python Programming