SoFunction
Updated on 2024-10-29

How to implement chained calls in python

We can see this writeup when querying the database using Django's models:

form  import XXX
query = ()
query = (name=123, age=456).filter(salary=999)

Inside this writeup, the query object has afiltermethod, the return data from this method can also continue to call thefiltermethod, which can be called on indefinitely in this way.

How is this writeup achieved?

If we write a class method directly, let's see if we can call it that way:

class Query:
    def filter(self):
        pass

query = Query()
().filter()

direct-to-()The returned result is called againfilterThis is because the method will return an error if no return statement is explicitly written. This is because when the return statement is not explicitly written, the method will returnNoneand None objects are not calledfilterMethodology.

So what has a filter method? Obviously our query object has a filter method. So how do we get this method to return itself as an object?

At this point, we need to look at the first parameter we always write when defining class methodsselfup. It's inside almost every class method. All people know is that you can call a class method from inside a class with the(), when calling class attributes you can use the, so has there been any thinking about what would happen to this thing if it was used on its own?

In fact.selfIt refers to the object itself after the class is instantiated into an object. And this object obviously hasfiltermethod. So let's modify thefiltermethod, have it returnself:

class Query:
    def filter(self):
        return self

query = Query()
().filter()

As you can see from the image, it doesn't report errors anymore. So back to the very beginning, how is chaining calls inside Django to pass in query parameters implemented?

There is actually aInert queriesof the problem.

When we keep calling.filter()method, Django will cache all these query conditions, and only when we need to get the results, or query how many pieces of data satisfy the conditions, it will actually connect to the database to query.

So we're going to simulate that environment here by caching the query conditions.

Then in order to get the name of the parameter passed in when the method is called, we have to use the**kwargsParameter. This parameter accepts all arguments of the form key=value:

class Query():
    def __init__(self):
        self.query_condition = {}

    def filter(self, **kwargs):
        self.query_condition.update(kwargs)
        return self
        
query = Query()
a = (name='kingname').filter(age__gt=15, address='yyyyyy').filter(salary=99999)
print(query.query_condition)

The running effect is shown below:

When you really need to output the results, you can then use these cached conditions to go to the database and query the results.

Above is how to achieve chained calls in python in detail, more information about python to achieve chained calls please pay attention to my other related articles!