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