Apa itu "bisa dipanggil"?


311

Sekarang sudah jelas apa itu metaclass , ada konsep terkait yang saya gunakan sepanjang waktu tanpa mengetahui apa artinya sebenarnya.

Saya kira semua orang pernah membuat kesalahan dengan tanda kurung, menghasilkan pengecualian "objek tidak dapat dipanggil". Terlebih lagi, menggunakan __init__dan__new__ menyebabkan bertanya-tanya untuk apa darah ini __call__dapat digunakan.

Bisakah Anda memberi saya beberapa penjelasan, termasuk contoh dengan metode ajaib?


Jawaban:


309

Callable adalah apa saja yang bisa dipanggil.

The built-in callable (PyCallable_Check di objects.c) memeriksa apakah argumen adalah baik:

  • turunan dari kelas dengan __call__metode atau
  • adalah tipe yang memiliki anggota tp_call (c struct) yang bukan nol yang menunjukkan kemampuan panggilan sebaliknya (seperti dalam fungsi, metode, dll.)

Metode yang dinamai __call__adalah ( sesuai dengan dokumentasi )

Disebut ketika instance '' disebut '' sebagai fungsi

Contoh

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

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

6
Perhatikan bahwa builtin callable sedang dihapus di Python 3.0 untuk memeriksa panggilan
Eli Courtwright

13
@Eli: Hmm itu terdengar seperti langkah yang sangat buruk. callablebenar-benar memberi tahu Anda jika ada sesuatu yang bisa dipanggil atau tidak, saat memeriksa __call__tidak ada yang memberi tahu Anda; Jika suatu objek omenyediakan __getattribute__atau __getattr__, hasattr(o, '__call__')dapat mengembalikan True, namun omasih tidak dapat dipanggil karena Python melompati __getattribute__dan __getattr__untuk panggilan. Satu-satunya cara nyata yang tersisa untuk memeriksa apakah ada sesuatu yang dapat dipanggil adalah EAFP.
L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳

49
@ Longpoke: Hanya untuk catatan, silakan lihat dokumentasi untuk callable()di Python 3.x : " Fungsi ini pertama kali dihapus di Python 3.0 dan kemudian dibawa kembali dengan Python 3.2. ".
Tadeck

Tampaknya dalam python 3.8 hanya keberadaan tp_calldiperiksa. Lihat implementasi PyCallable_Check , ini 3 baris.
Michele Piccolini

84

Dari sumber Python objek.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;
    }
}

Ia mengatakan:

  1. Jika suatu objek adalah turunan dari beberapa kelas maka itu dapat dipanggil jika memiliki __call__atribut.
  2. Kalau tidak, objek xitu bisa dipanggil iff x->ob_type->tp_call != NULL

Desciption dari tp_call bidang :

ternaryfunc tp_callPointer opsional ke fungsi yang mengimplementasikan pemanggilan objek. Ini harus NULL jika objek tidak dapat dipanggil. Tanda tangan sama dengan untuk PyObject_Call (). Bidang ini diwarisi oleh subtipe.

Anda selalu dapat menggunakan callablefungsi bawaan untuk menentukan apakah objek yang diberikan dapat dipanggil atau tidak; atau lebih baik lagi panggil saja dan tangkap TypeErrornanti. callabledihapus dalam Python 3.0 dan 3.1, gunakan callable = lambda o: hasattr(o, '__call__')atau isinstance(o, collections.Callable).

Contoh, implementasi cache yang disederhanakan:

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    

Pemakaian:

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

Contoh dari perpustakaan standar, file site.py, definisi built-in exit()dan quit()fungsi:

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

10
Saya menemukan contoh untuk metode panggilan sangat menyesatkan karena mencampurkannya dengan resep untuk caching dan dekorator, yang tidak menambah apa pun pada pemahaman panggilan
Florian Bösch

3
JF Sebastian, juga menumpuk lebih banyak contoh yang Anda salin & tempel dari tempat lain yang tidak minimal tidak membantu.
Florian Bösch

20
@ JF Sebastian: Ini BS bahwa lebih banyak contoh kehidupan lebih baik. Saya bisa menunjukkan kepada Anda kode seperti hidup yang akan membuat Anda menangis sebagai contoh. Contoh-contoh sederhana juga berfungsi, dan mereka bekerja lebih baik untuk mengilustrasikan sesuatu karena tidak mengganggu.
Florian Bösch

5
Anda menjelaskan apa yang bisa dipanggil, tetapi Anda memberi contoh bagaimana menggunakan objek yang bisa dipanggil untuk menentukan dekorator. Saya tahu ini adalah penggunaan callable yang khas tetapi ini dapat membingungkan pembaca yang hanya ingin tahu apa yang bisa dipanggil dan bagaimana menggunakan callable . Saya lebih suka jawaban @Florian Bösch.
KFL

2
@Kay: Saya juga suka jawaban @Florian Bösch (dalam bentuk saat ini). btw, dekorator bukanlah penggunaan khas dari "callable". Yang paling khas "callables" adalah fungsi / metode seperti def f(): ..., dan kelas objek seperti class C: ...yaitu, f, ''.strip, len, dan Csemua callable. Contoh yang memiliki __call__()metode di kelas mereka relatif jarang.
jfs

37

Callable adalah objek yang memungkinkan Anda untuk menggunakan kurung bulat () dan akhirnya melewati beberapa parameter, seperti fungsi.

Setiap kali Anda mendefinisikan fungsi, python membuat objek yang bisa dipanggil. Sebagai contoh, Anda bisa mendefinisikan fungsi func dengan cara ini (sama saja):

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

func = a()

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

Anda bisa menggunakan metode ini daripada metode seperti doit atau run , saya pikir itu lebih jelas untuk melihat obj () daripada obj.doit ()


37

Biarkan saya jelaskan mundur:

Pertimbangkan ini ...

foo()

... sebagai gula sintaksis untuk:

foo.__call__()

Di mana foobisa ada objek yang merespons __call__. Ketika saya mengatakan objek apa pun, maksud saya adalah: tipe bawaan, kelas Anda sendiri, dan instance mereka.

Dalam hal tipe bawaan, saat Anda menulis:

int('10')
unicode(10)

Anda pada dasarnya melakukan:

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

Itu juga mengapa Anda tidak memiliki foo = new intdalam Python: Anda hanya membuat objek kelas mengembalikan turunannya __call__. Cara Python memecahkan ini sangat elegan menurut saya.


Anda pada dasarnya melakukan type(int).__call__(int, '10')dan type(unicode).__call__(unicode, '10'). Dunders selalu dipanggil di kelas mereka, bukan melalui instance. Dan mereka juga tidak pernah melewati metaclass. Untuk sebagian besar kasus, itu hanya nitpick, tetapi terkadang penting.
Fisikawan Gila

11

A Callable adalah objek yang memiliki __call__metode. Ini berarti Anda dapat memalsukan fungsi yang dapat dipanggil atau melakukan hal-hal yang rapi seperti Aplikasi Fungsi Parsial di mana Anda mengambil fungsi dan menambahkan sesuatu yang meningkatkannya atau mengisi beberapa parameter, mengembalikan sesuatu yang dapat dipanggil secara bergiliran (dikenal sebagai Currying) di lingkaran pemrograman fungsional) ).

Kesalahan tipografi tertentu akan membuat penerjemah berusaha memanggil sesuatu yang tidak Anda inginkan, seperti (misalnya) string. Ini dapat menghasilkan kesalahan ketika penerjemah mencoba untuk menjalankan aplikasi yang tidak dapat dipanggil. Anda dapat melihat ini terjadi dalam juru bahasa python dengan melakukan sesuatu seperti transkrip di bawah ini.

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

9

__call__ membuat objek apa pun bisa dipanggil sebagai fungsi.

Contoh ini akan menampilkan 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)

7

Sederhananya, "callable" adalah sesuatu yang bisa disebut seperti metode. Fungsi bawaan "callable ()" akan memberi tahu Anda apakah ada sesuatu yang tampaknya dapat dipanggil, seperti halnya memeriksa properti panggilan . Fungsi dapat dipanggil seperti halnya kelas, instance kelas dapat dipanggil. Lihat lebih lanjut tentang ini di sini dan di sini .


5

Dalam Python, callable adalah objek yang jenisnya memiliki __call__metode:

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

Sesimpel itu :)

Ini tentu saja dapat kelebihan beban:

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

3

Untuk memeriksa fungsi atau metode kelas apakah dapat dipanggil atau tidak, itu berarti kita dapat memanggil fungsi itu.

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

1
Apakah Anda yakin callable(obj.__init___)tidak memiliki garis bawah ekstra (seperti di AttributeError)? Jika tidak, apakah Anda yakin jawabannya bukan Trueuntuk yang itu?
Fisikawan Gila

2

Ini adalah sesuatu yang Anda dapat menempatkan "(args)" setelah dan berharap itu berfungsi. Callable biasanya merupakan metode atau kelas. Metode dipanggil, kelas akan dipakai.


2

callable menerapkan __call__metode khusus sehingga objek apa pun dengan metode seperti itu dapat dipanggil.


Sebuah instance di mana Anda mendefinisikan __call__tidak akan dapat dipanggil jika kelas tidak mendefinisikan metode seperti itu.
Fisikawan Gila

2

Callable adalah jenis atau kelas "Fungsi atau Metode Bangun" dengan pemanggilan metode

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

Contoh: cetak adalah objek yang bisa dipanggil. Dengan fungsi bawaan __call__ Saat Anda menjalankan fungsi cetak , Python membuat objek tipe cetak dan memanggil metode __call__ dengan meneruskan parameter jika ada.

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

Terima kasih. Salam, Maris


1
Beberapa info di sini benar salah. Misalnya "Ketika Anda menjalankan printfungsi, Python membuat objek tipe cetak dan memanggil metode __call__". Python tidak membuat objek cetak. Itu hanya menyebut sesuatu yang setara dengan type(print).__call__(print, *args, **kwargs). Dan kalimat pertama tidak masuk akal. Anda tampaknya membingungkan objek yang bisa dipanggil dan "dapat dipanggil" fungsinya.
Fisikawan Gila
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.