[python] __init__와 __call__의 차이점은 무엇입니까?

__init____call__방법 의 차이점을 알고 싶습니다 .

예를 들면 다음과 같습니다.

class test:

  def __init__(self):
    self.a = 10

  def __call__(self): 
    b = 20



답변

첫 번째는 새로 작성된 객체를 초기화하는 데 사용되며이를 수행하는 데 사용되는 인수를 수신합니다.

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__


답변

__call__()메타 클래스에서 커스텀 메소드를 정의 하면 클래스의 인스턴스를 함수로 호출 할 수 있지만 인스턴스 자체를 항상 수정하는 것은 아닙니다.

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

In [2]: a = A()
init

In [3]: a()
call


답변

파이썬에서 함수는 일류 객체입니다. 즉, 함수 참조는 다른 함수 및 / 또는 메소드에 입력으로 전달되어 그 안에서 실행될 수 있습니다.

클래스 인스턴스 (일명 개체)는 마치 함수 인 것처럼 취급 할 수 있습니다. 다른 메서드 / 함수로 전달하고 호출합니다. 이를 위해서는 __call__클래스 기능이 특화되어야합니다.

def __call__(self, [args ...])
가변 개수의 인수를 입력으로 사용합니다. 가정 x클래스의 인스턴스 인 X, x.__call__(1, 2)호출과 유사 x(1,2)또는 함수 자체를 인스턴스 .

Python에서는 __init__()클래스 생성자뿐만 아니라 클래스 생성자로 올바르게 정의됩니다 __del__(). 따라서,이 사이에 그물 구별입니다 __init__()__call__()다음 첫 번째 클래스 최대의 인스턴스를 구축, 두 번째는 인스턴스하게 호출 함수가 객체 자체의 수명에 영향을주지 않고 수 (즉 것처럼 __call__건설 / 파괴 라이프 사이클에 영향을주지 않습니다)하지만를 내부 상태를 수정할 수 있습니다 (아래 그림 참조).

예.

class Stuff(object):

    def __init__(self, x, y, range):
        super(Stuff, self).__init__()
        self.x = x
        self.y = y
        self.range = range

    def __call__(self, x, y):
        self.x = x
        self.y = y
        print '__call__ with (%d,%d)' % (self.x, self.y)

    def __del__(self):
        del self.x
        del self.y
        del self.range

>>> s = Stuff(1, 2, 3)
>>> s.x
1
>>> s(7, 8)
__call__ with (7,8)
>>> s.x
7


답변

__call__클래스의 인스턴스를 호출 가능하게 만듭니다. 왜 필요할까요?

기술적 __init__으로 __new__객체가 생성 될 때 한 번 호출 되므로 초기화 할 수 있습니다.

그러나 객체를 재정의하고, 객체를 다 사용했다고 말하고, 새로운 객체가 필요할 수있는 시나리오가 많이 있습니다. 로 __call__가 새 것처럼 당신이 동일한 개체를 다시 정의 할 수 있습니다.

이것은 하나의 경우에 불과하며 더 많은 것이있을 수 있습니다.


답변

>>> class A:
...     def __init__(self):
...         print "From init ... "
... 
>>> a = A()
From init ... 
>>> a()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: A instance has no __call__ method
>>> 
>>> class B:
...     def __init__(self):
...         print "From init ... "
...     def __call__(self):
...         print "From call ... "
... 
>>> b = B()
From init ... 
>>> b()
From call ... 
>>> 


답변

__init____call__메소드를 객체로 여러 번 호출 할 수있는 생성자로 취급됩니다 . __init____call__함수 모두 기본 인수를 사용합니다.


답변

피보나치 시리즈에서 고정 된 수의 용어를 인쇄하려고한다고 가정 해 보겠습니다. 피보나치 시리즈의 처음 두 항은 1입니다. 예 : 1, 1, 2, 3, 5, 8, 13 ….

피보나치 번호가 포함 된 목록을 한 번만 초기화 한 후 업데이트해야합니다. 이제 __call__기능을 사용할 수 있습니다 . @mudit verma의 답변을 읽으십시오. 마치 객체를 함수로 호출 할 수 있지만 호출 할 때마다 다시 초기화하지 않는 것과 같습니다.

예 :

class Recorder:
    def __init__(self):
        self._weights = []
        for i in range(0, 2):
            self._weights.append(1)
        print self._weights[-1]
        print self._weights[-2]
        print "no. above is from __init__"

    def __call__(self, t):
        self._weights = [self._weights[-1], self._weights[-1] + self._weights[-2]]
        print self._weights[-1]
        print "no. above is from __call__"

weight_recorder = Recorder()
for i in range(0, 10):
    weight_recorder(i)

출력은 다음과 같습니다.

1
1
no. above is from __init__
2
no. above is from __call__
3
no. above is from __call__
5
no. above is from __call__
8
no. above is from __call__
13
no. above is from __call__
21
no. above is from __call__
34
no. above is from __call__
55
no. above is from __call__
89
no. above is from __call__
144
no. above is from __call__

__init__클래스가 처음으로 인스턴스화되었을 때 한 번만 출력 이 호출 된 것을 관찰하면 나중에 다시 초기화하지 않고 오브젝트가 호출되었습니다.