Python __call__ special method practical example

后端 未结 14 1509
感动是毒
感动是毒 2020-11-28 00:28

I know that __call__ method in a class is triggered when the instance of a class is called. However, I have no idea when I can use this special method, because

相关标签:
14条回答
  • 2020-11-28 00:57

    This example uses memoization, basically storing values in a table (dictionary in this case) so you can look them up later instead of recalculating them.

    Here we use a simple class with a __call__ method to calculate factorials (through a callable object) instead of a factorial function that contains a static variable (as that's not possible in Python).

    class Factorial:
        def __init__(self):
            self.cache = {}
        def __call__(self, n):
            if n not in self.cache:
                if n == 0:
                    self.cache[n] = 1
                else:
                    self.cache[n] = n * self.__call__(n-1)
            return self.cache[n]
    
    fact = Factorial()
    

    Now you have a fact object which is callable, just like every other function. For example

    for i in xrange(10):                                                             
        print("{}! = {}".format(i, fact(i)))
    
    # output
    0! = 1
    1! = 1
    2! = 2
    3! = 6
    4! = 24
    5! = 120
    6! = 720
    7! = 5040
    8! = 40320
    9! = 362880
    

    And it is also stateful.

    0 讨论(0)
  • 2020-11-28 00:57

    Class-based decorators use __call__ to reference the wrapped function. E.g.:

    class Deco(object):
        def __init__(self,f):
            self.f = f
        def __call__(self, *args, **kwargs):
            print args
            print kwargs
            self.f(*args, **kwargs)
    

    There is a good description of the various options here at Artima.com

    0 讨论(0)
  • 2020-11-28 01:02

    Specify a __metaclass__ and override the __call__ method, and have the specified meta classes' __new__ method return an instance of the class, viola you have a "function" with methods.

    0 讨论(0)
  • 2020-11-28 01:02

    This is too late but I'm giving an example. Imagine you have a Vector class and a Point class. Both take x, y as positional args. Let's imagine you want to create a function that moves the point to be put on the vector.

    4 Solutions

    • put_point_on_vec(point, vec)

    • Make it a method on the vector class. e.g my_vec.put_point(point)

    • Make it a method on the Point class. my_point.put_on_vec(vec)
    • Vector implements __call__, So you can use it like my_vec_instance(point)

    This is actually part of some examples I'm working on for a guide for dunder methods explained with Maths that I'm gonna release sooner or later.

    I left the logic of moving the point itself because this is not what this question is about

    0 讨论(0)
  • 2020-11-28 01:04

    __call__ is also used to implement decorator classes in python. In this case the instance of the class is called when the method with the decorator is called.

    class EnterExitParam(object):
    
        def __init__(self, p1):
            self.p1 = p1
    
        def __call__(self, f):
            def new_f():
                print("Entering", f.__name__)
                print("p1=", self.p1)
                f()
                print("Leaving", f.__name__)
            return new_f
    
    
    @EnterExitParam("foo bar")
    def hello():
        print("Hello")
    
    
    if __name__ == "__main__":
        hello()
    
    0 讨论(0)
  • 2020-11-28 01:04

    We can use __call__ method to use other class methods as static methods.

        class _Callable:
            def __init__(self, anycallable):
                self.__call__ = anycallable
    
        class Model:
    
            def get_instance(conn, table_name):
    
                """ do something"""
    
            get_instance = _Callable(get_instance)
    
        provs_fac = Model.get_instance(connection, "users")             
    
    0 讨论(0)
提交回复
热议问题