web-dev-qa-db-ja.com

「呼び出し可能」とは何ですか?

これで明らかになりました メタクラスとは 、それが本当に何を意味するのかわからずにいつも使っているという関連概念があります。

誰もが括弧で間違えたために、「オブジェクトは呼び出し不可能」という例外が発生したと思います。さらに、__init____new__を使うことは、この血まみれの__call__が何のために使われることができるか疑問に思います。

あなたは私にマジックメソッドを使った例を含めていくつかの説明をお願いします。

273
e-satis

呼び出し可能オブジェクトは、呼び出すことができるものすべてです。

組み込みcallable(objects.cのPyCallable_Check) は引数が以下のいずれかであるかどうかをチェックします。

  • _ CALL _メソッドを持つクラスのインスタンス
  • null以外の--- tp_call(c struct)メンバーを持つ型で、そうでない場合は呼び出し可能性を示します(関数、メソッドなど)。

_ CALL _という名前のメソッドは( ドキュメントによると )です。

インスタンスが関数として「呼ばれる」ときに呼び出されます

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

foo_instance = Foo()
foo_instance() #this is calling the __call__ method
278
Florian Bösch

Pythonのソースから 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は呼び出し可能ですiffx->ob_type->tp_call != NULL

tp_callフィールド の説明:

ternaryfunc tp_callオブジェクトの呼び出しを実装する関数へのオプションのポインタ。オブジェクトが呼び出し可能でない場合、これはNULLであるべきです。シグネチャはPyObject_Call()と同じです。このフィールドはサブタイプによって継承されます。

与えられたオブジェクトが呼び出し可能かどうかを判断するために、常に組み込みのcallable関数を使うことができます。もっといいのですが、呼び出してTypeErrorを後でキャッチするだけです。 callableはPython 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')
77
jfs

呼び出し可能オブジェクトは、関数と同じように、丸括弧()を使用して最終的にいくつかのパラメーターを渡すことができるオブジェクトです。

関数を定義するたびに、pythonは呼び出し可能オブジェクトを作成します。たとえば、次のようにして関数funcを定義できます(それは同じです)。

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

func = a()

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

あなたはdoitrunのようなメソッドの代わりにこのメソッドを使うことができます。

35
Andrea Ambu

逆に説明させてください。

このことを考慮...

foo()

...の構文糖として

foo.__call__()

foo__call__に応答する任意のオブジェクトです。私が任意のオブジェクトを言うとき、私はそれを意味します:組み込み型、あなた自身のクラスとそれらのインスタンス。

組み込み型の場合、次のように書くと

int('10')
unicode(10)

あなたは本質的にやっています:

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

これが、Pythonにfoo = new intがない理由でもあります。クラスオブジェクトが__call__上でそのインスタンスを返すようにするだけです。 Pythonがこれを解決する方法は、私の考えでは非常に優雅です。

31
hcalves

Callableは__call__メソッドを持つオブジェクトです。つまり、呼び出し可能な関数を偽造したり、 Partial Function Application という関数を使ってそれを強化したり、一部のパラメーターを埋めたりして、順番に呼び出すことができるようにすることができます。関数プログラミングの分野では カレー として知られています。

特定のタイプミスがあると、通訳者は意図していないもの(たとえば文字列など)を呼び出そうとします。これにより、インタプリタが呼び出し不可能なアプリケーションを実行しようとするとエラーが発生する可能性があります。あなたは以下のトランスクリプトのような何かをすることによってpythonインタプリタでこれが起こっているのを見ることができます。

[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
>>> 

簡単に言うと、「呼び出し可能」とはメソッドのように呼び出すことができるものです。組み込み関数 "callable()"は、callプロパティをチェックするのと同様に、何かが呼び出し可能であるように見えるかどうかを教えてくれます。関数はクラスと同様に呼び出し可能であり、クラスインスタンスは呼び出し可能です。詳しくは herehere をご覧ください。

7
Joe Skora

__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)
6
MvdD

Pythonでは、callableは__call__メソッドを持つオブジェクトです。

>>> class Foo:
...  pass
... 
>>> class Bar(object):
...  pass
... 
>>> type(Foo).__call__(Foo)
<__main__.Foo instance at 0x711440>
>>> type(Bar).__call__(Bar)
<__main__.Bar object at 0x712110>
>>> def foo(bar):
...  return bar
... 
>>> type(foo).__call__(foo, 42)
42

それと同じくらい簡単:)

もちろんこれは過負荷になる可能性があります。

>>> class Foo(object):
...  def __call__(self):
...   return 42
... 
>>> f = Foo()
>>> f()
42
5
Armin Ronacher

クラスの関数やメソッドを呼び出すことができるかどうかは、その関数を呼び出すことができることを意味します。

Class A:
    def __init__(self,val):
        self.val = val
    def bar(self):
        print "bar"

obj = A()      
callable(obj.bar)
True
callable(obj.__init___)
False
def foo(): return "s"
callable(foo)
True
callable(foo())
False
2
Ravi Singh

それはあなたが "(args)"の後に置くことができてそれが機能すると期待できるものです。呼び出し可能オブジェクトは通常、メソッドまたはクラスです。メソッドが呼び出され、クラスがインスタンス化されます。

2
Kevin Conner

呼び出し可能は、メソッドを持つ "組み込み関数またはメソッド"の型またはクラス呼び出しです。

>>> type(callable)
<class 'builtin_function_or_method'>
>>>

例:printは呼び出し可能オブジェクトです。組み込み関数の場合_ CALL _print関数を呼び出すと、Pythonはprint型のオブジェクトを作成し、そのメソッドを呼び出します_CALL _もしあればパラメータを渡します。

>>> type(print)
<class 'builtin_function_or_method'>
>>> print.__call__(10)
10
>>> print(10)
10
>>>

ありがとうございました。よろしく、マリス

1
maris

呼び出し可能オブジェクトは__call__特殊メソッドを実装しているため、そのようなメソッドを持つオブジェクトは呼び出し可能です。

1
cobie