我想知道__init__和__call__方法之间的区别。

例如:

class test:

  def __init__(self):
    self.a = 10

  def __call__(self): 
    b = 20

当前回答

定义自定义__call__()方法允许将类的实例作为函数调用,而不总是修改实例本身。

In [1]: class A:
   ...:     def __init__(self):
   ...:         print "init"
   ...:         
   ...:     def __call__(self):
   ...:         print "call"
   ...:         
   ...:         

In [2]: a = A()
init

In [3]: a()
call

其他回答

__init__将被视为构造函数,其中__call__方法可以被对象调用任意次数。__init__和__call__函数都接受默认参数。

我们可以使用调用方法来使用其他类方法作为静态方法。

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")  

第一个用于初始化新创建的对象,并接收用于初始化的参数:

class Foo:
    def __init__(self, a, b, c):
        # ...

x = Foo(1, 2, 3) # __init__

第二部分实现函数调用操作符。

class Foo:
    def __call__(self, a, b, c):
        # ...

x = Foo()
x(1, 2, 3) # __call__

我想提供一些捷径和语法糖,以及一些可以使用的技术,但我在当前的答案中没有看到它们。

实例化类并立即调用它

在很多情况下,例如当需要做一个APi请求时,逻辑被封装在一个类中,我们真正需要的只是把数据给那个类,并立即作为一个单独的实体运行它,实例化类可能不需要。这就是

instance = MyClass() # instanciation
instance() # run the instance.__call__()
# now instance is not needed 

相反,我们可以这样做。

class HTTPApi:

    def __init__(self, val1, val2):
        self.val1 = val1
        self.val2 = val2

    def __call__(self, *args, **kwargs):
        return self.run(args, kwargs)

    def run(self, *args, **kwargs):
        print("hello", self.val1, self.val2, args, kwargs)
        
if __name__ == '__main__':
    # Create a class, and call it
    (HTTPApi("Value1", "Value2"))("world", 12, 213, 324, k1="one", k2="two")


给调用另一个现有的方法

我们也可以向__call__声明一个方法,而不需要创建一个实际的__call__方法。

class MyClass:

    def __init__(self, val1, val2):
        self.val1 = val1
        self.val2 = val2

    def run(self, *args, **kwargs):
        print("hello", self.val1, self.val2, args, kwargs)

    __call__ = run

if __name__ == '__main__':
    (MyClass("Value1", "Value"))("world", 12, 213, 324, k1="one", k2="two")

这允许声明另一个全局函数而不是一个方法,无论出于什么原因(可能有一些原因,例如你不能修改该方法,但你需要由类调用它)。

def run(self, *args, **kwargs):
    print("hello",self.val1, self.val2,  args, kwargs)

class MyClass:

    def __init__(self, val1, val2):
        self.val1 = val1
        self.val2 = val2

    __call__ = run

if __name__ == '__main__':
    (MyClass("Value1", "Value2"))("world", 12, 213, 324, k1="one", k2="two")

因此,当你创建任何类的实例并初始化实例变量时,__init__也会被调用。

例子:

class User:

    def __init__(self,first_n,last_n,age):
        self.first_n = first_n
        self.last_n = last_n
        self.age = age

user1 = User("Jhone","Wrick","40")

当你像调用其他函数一样调用对象时,会调用__call__。

例子:

class USER:
    def __call__(self,arg):
        "todo here"
         print(f"I am in __call__ with arg : {arg} ")


user1=USER()
user1("One") #calling the object user1 and that's gonna call __call__ dunder functions