[python] “호출 가능”이란 무엇입니까?

메타 클래스가 무엇인지 분명히 알았 으므로 , 그것이 실제로 무엇을 의미하는지 알지 못하고 항상 사용하는 관련 개념이 있습니다.

모든 사람이 한 번 괄호로 실수를하여 “객체를 호출 할 수 없음”예외가 발생했다고 가정합니다. 사용, 무엇보다 __init__하고 __new__이 피 묻은이 궁금해으로 이어질 __call__사용할 수 있습니다.

마법 방법을 사용한 예를 포함하여 설명을 해 주시겠습니까?



답변

호출 가능은 호출 할 수있는 모든 것입니다.

내장 호출 (objects.c에서 PyCallable_Check) 검사는 인수가 하나 인 경우 :

  • __call__메소드 가있는 클래스의 인스턴스 또는
  • 함수, 메소드 등에서 호출 가능성을 나타내는 널이 아닌 tp_call (c struct) 멤버 가있는 유형입니다 .

명명 된 방법 __call__은 ( 문서에 따라 )

인스턴스가 함수로“호출 ”될 때 호출됩니다.

class Foo:
  def __call__(self):
    print 'called'

foo_instance = Foo()
foo_instance() #this is calling the __call__ method


답변

파이썬 소스에서 object.c :

/* Test whether an object can be called */

int
PyCallable_Check(PyObject *x)
{
    if (x == NULL)
        return 0;
    if (PyInstance_Check(x)) {
        PyObject *call = PyObject_GetAttrString(x, "__call__");
        if (call == NULL) {
            PyErr_Clear();
            return 0;
        }
        /* Could test recursively but don't, for fear of endless
           recursion if some joker sets self.__call__ = self */
        Py_DECREF(call);
        return 1;
    }
    else {
        return x->ob_type->tp_call != NULL;
    }
}

그것은 말한다 :

  1. 객체가 어떤 클래스의 인스턴스라면 호출 가능 IFF에 는이 __call__속성을.
  2. 다른 개체 x 호출이다 IFF x->ob_type->tp_call != NULL

의 설명 tp_call 분야 :

ternaryfunc tp_call객체 호출을 구현하는 함수에 대한 선택적 포인터입니다. 객체를 호출 할 수없는 경우 NULL이어야합니다. 서명은 PyObject_Call ()과 동일합니다. 이 필드는 하위 유형으로 상속됩니다.

항상 내장 callable함수를 사용하여 주어진 객체의 호출 가능 여부를 결정할 수 있습니다 . 또는 더 나은 방법으로 전화를 걸어 TypeError나중에 잡을 수 있습니다. callablePython 3.0 및 3.1에서 제거되면 callable = lambda o: hasattr(o, '__call__')또는을 사용하십시오 isinstance(o, collections.Callable).

간단한 캐시 구현 예 :

class Cached:
    def __init__(self, function):
        self.function = function
        self.cache = {}

    def __call__(self, *args):
        try: return self.cache[args]
        except KeyError:
            ret = self.cache[args] = self.function(*args)
            return ret    

용법:

@Cached
def ack(x, y):
    return ack(x-1, ack(x, y-1)) if x*y else (x + y + 1) 

표준 라이브러리, 파일 site.py, 내장 exit()quit()함수 정의의 예 :

class Quitter(object):
    def __init__(self, name):
        self.name = name
    def __repr__(self):
        return 'Use %s() or %s to exit' % (self.name, eof)
    def __call__(self, code=None):
        # Shells like IDLE catch the SystemExit, but listen when their
        # stdin wrapper is closed.
        try:
            sys.stdin.close()
        except:
            pass
        raise SystemExit(code)
__builtin__.quit = Quitter('quit')
__builtin__.exit = Quitter('exit')


답변

콜 러블은 객체를 사용하여 괄호 ()를 사용하고 함수와 마찬가지로 일부 매개 변수를 전달할 수 있습니다.

함수를 정의 할 때마다 파이썬은 호출 가능한 객체를 만듭니다. 예를 들어, func 함수 를 다음과 같이 정의 할 수 있습니다 (동일 함).

class a(object):
    def __call__(self, *args):
        print 'Hello'

func = a()

# or ... 
def func(*args):
    print 'Hello'

doit 또는 run 과 같은 메소드 대신이 메소드를 사용할 수 있습니다. obj.doit ()보다 obj ()를 보는 것이 더 분명하다고 생각합니다


답변

거꾸로 설명하겠습니다 :

이걸 고려하세요…

foo()

…의 구문 설탕으로 :

foo.__call__()

foo응답하는 객체가 어디에 있을 수 있습니다 __call__. 객체를 말하면 내장 유형, 클래스 및 인스턴스입니다.

내장 유형의 경우 다음을 쓸 때

int('10')
unicode(10)

당신은 본질적으로하고 있습니다 :

int.__call__('10')
unicode.__call__(10)

그렇기 때문에 foo = new int파이썬 에는없는 이유가 있습니다 . 클래스 객체가에 대한 인스턴스를 반환하도록하십시오 __call__. 파이썬이 이것을 해결하는 방식은 제 생각에는 매우 우아합니다.


답변

Callable은 __call__메소드 가있는 객체입니다 . 즉, 호출 가능한 함수를 가짜로 만들거나 부분 함수 응용 프로그램 과 같이 깔끔한 기능 을 수행하여 함수를 가져 와서 기능을 향상 시키거나 매개 변수 중 일부를 채우고 차례로 호출 할 수있는 것을 반환 할 수 있습니다 ( Currying 이라고 함) 함수형 프로그래밍 원에 ).

특정 인쇄상의 오류로 인해 인터프리터는 문자열과 같이 의도하지 않은 것을 호출하려고합니다. 인터프리터가 호출 할 수없는 응용 프로그램을 실행하려고하면 오류가 발생할 수 있습니다. 아래의 스크립트와 같은 것을 수행하면 파이썬 인터프리터에서 이런 일이 발생하는 것을 볼 수 있습니다.

[nigel@k9 ~]$ python
Python 2.5 (r25:51908, Nov  6 2007, 15:55:44)
[GCC 4.1.2 20070925 (Red Hat 4.1.2-27)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 'aaa'()    # <== Here we attempt to call a string.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object is not callable
>>> 


답변

__call__ 모든 객체를 함수로 호출 할 수있게합니다.

이 예는 8을 출력합니다.

class Adder(object):
  def __init__(self, val):
    self.val = val

  def __call__(self, val):
    return self.val + val

func = Adder(5)
print func(3)


답변

간단히 말해서 “호출 가능”은 메소드처럼 호출 될 수있는 것입니다. 내장 함수 “callable ()”은 호출 속성을 확인할 때 호출 가능한 것으로 보이는지 여부를 알려줍니다 . 클래스와 마찬가지로 함수를 호출 할 수 있으며 클래스 인스턴스를 호출 할 수 있습니다. 이에 대한 자세한 내용은 여기여기를 참조 하십시오 .