Saya punya variabel,, x
dan saya ingin tahu apakah itu menunjuk ke suatu fungsi atau tidak.
Saya berharap bisa melakukan sesuatu seperti:
>>> isinstance(x, function)
Tapi itu memberi saya:
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'function' is not defined
Alasan saya memilih itu karena
>>> type(x)
<type 'function'>
insepct.getsource
berbagai objek, dan sebenarnya tidak masalah apakah objek itu dapat dipanggil tetapi apakah itu sesuatu yang akan memberikan 'fungsi' untuktype(obj)
. Karena google membawa saya ke sini, saya akan mengatakan komentar AsTeR adalah jawaban yang paling berguna (untuk saya). Ada banyak tempat lain di internet bagi orang untuk menemukan__call__
ataucallable
.Jawaban:
Jika ini untuk Python 2.x atau untuk Python 3.2+, Anda juga dapat menggunakan
callable()
. Dulu ditinggalkan, tetapi sekarang tidak ditinggalkan, sehingga Anda dapat menggunakannya lagi. Anda dapat membaca diskusi di sini: http://bugs.python.org/issue10518 . Anda dapat melakukan ini dengan:Jika ini untuk Python 3.x tetapi sebelum 3.2, periksa apakah objek memiliki
__call__
atribut. Anda dapat melakukan ini dengan:Pendekatan yang sering disarankan
types.FunctionTypes
tidak benar karena gagal untuk menutupi banyak kasus yang Anda mungkin ingin lulus, seperti dengan builtin:Cara yang tepat untuk memeriksa properti dari objek yang diketik bebek adalah dengan menanyakannya apakah mereka berdetak, tidak melihat apakah mereka muat dalam wadah berukuran bebek. Jangan gunakan
types.FunctionType
kecuali Anda memiliki ide yang sangat spesifik tentang apa fungsi itu.sumber
Tipe builtin yang tidak memiliki konstruktor di namespace built-in (mis. Fungsi, generator, metode) ada di
types
modul. Anda dapat menggunakantypes.FunctionType
dalamisinstance
panggilan:Perhatikan bahwa ini menggunakan gagasan "fungsi" yang sangat spesifik yang biasanya bukan yang Anda butuhkan. Misalnya, ia menolak
zip
(secara teknis sebuah kelas):open
(fungsi bawaan memiliki tipe yang berbeda):dan
random.shuffle
(secara teknis metoderandom.Random
instance tersembunyi ):Jika Anda melakukan sesuatu yang spesifik untuk
types.FunctionType
instance, seperti mendekompilasi bytecode mereka atau memeriksa variabel closure, gunakantypes.FunctionType
, tetapi jika Anda hanya perlu objek yang dapat dipanggil seperti fungsi, gunakancallable
.sumber
isinstance(f, (types.FunctionType, types.BuiltinFunctionType, functools.partial))
atau memeriksaf.func
dalam kasus seperti itu.@foo
yang dapat saya gunakan sebagai@foo
dan sebagai@foo(some_parameter)
. Kemudian perlu memeriksa apa yang dipanggil dengan, misalnya fungsi untuk menghias (kasus pertama) atau parameter (kasus kedua, di mana ia perlu mengembalikan dekorator lebih lanjut).types.BuiltinFunctionType
juga jenis ( "normal") built-in metode , yang Anda mungkin tidak ingin mengizinkan, jika Anda tidak akan dengancallable
rute.Karena Python 2.1 Anda dapat mengimpor
isfunction
dariinspect
modul.sumber
open
danhasattr
.inspect.isfunction
docstring: "Kembalikan benar jika objek adalah fungsi yang ditentukan pengguna."Jawaban yang diterima adalah pada saat itu ditawarkan dianggap benar. Ternyata, ada ada pengganti untuk
callable()
, yang kembali Python 3.2: Secara khusus,callable()
pemeriksaan yangtp_call
bidang objek yang sedang diuji. Tidak ada yang setara dengan Python. Sebagian besar tes yang disarankan sebagian besar benar:Kita bisa melemparkan kunci inggris ke dalam ini dengan menghapus
__call__
dari kelas. Dan hanya untuk menjaga hal-hal ekstra menarik, tambahkan yang palsu__call__
ke instance!Perhatikan ini sebenarnya tidak bisa dipanggil:
callable()
mengembalikan hasil yang benar:Tapi
hasattr
itu salah :can_o_spam
memang memiliki atribut itu; itu tidak digunakan saat memanggil instance.Bahkan lebih halus, ini
isinstance()
juga salah:Karena kami menggunakan pemeriksaan ini sebelumnya dan kemudian menghapus metode,
abc.ABCMeta
cache hasilnya. Bisa dibilang ini adalah bug diabc.ABCMeta
. Yang mengatakan, benar-benar tidak ada cara yang mungkin bisa menghasilkan hasil yang lebih akurat daripada hasilnya daripada dengan menggunakancallable()
sendiri, karenatypeobject->tp_call
metode slot tidak dapat diakses dengan cara lain.Gunakan saja
callable()
sumber
hasattr(o, '__call__')
pendekatan dan mengapacallable()
, jika tersedia, lebih unggul.Yang berikut harus mengembalikan boolean:
sumber
Alat 2to3 Python ( http://docs.python.org/dev/library/2to3.html ) menyarankan:
Tampaknya ini dipilih daripada
hasattr(x, '__call__')
metode karena http://bugs.python.org/issue7006 .sumber
callable()
untuk py3.3: bugs.python.org/issue10518#msg122309callable(x)
akan mengembalikan true jika objek yang diteruskan dapat dipanggil dengan Python, tetapi fungsi tidak ada di Python 3.0, dan berbicara dengan benar tidak akan membedakan antara:Anda akan mendapatkan
<class 'A'> True
dan<type function> True
sebagai output.isinstance
bekerja dengan sangat baik untuk menentukan apakah ada fungsi (cobaisinstance(b, types.FunctionType)
); jika Anda benar-benar tertarik mengetahui apakah sesuatu dapat dipanggil, Anda dapat menggunakanhasattr(b, '__call__')
atau hanya mencobanya.Ini, tentu saja, tidak akan memberi tahu Anda apakah itu bisa dipanggil tetapi melempar
TypeError
ketika dijalankan, atau tidak bisa dipanggil di tempat pertama. Itu mungkin tidak masalah bagi Anda.sumber
Jika Anda ingin mendeteksi segala sesuatu yang secara sintaksis tampak seperti fungsi: fungsi, metode, kesenangan bawaan / met, lambda ... tetapi mengecualikan objek yang dapat dipanggil (objek dengan
__call__
metode yang ditentukan), lalu coba yang ini:Saya membandingkan ini dengan kode
is*()
cek dalaminspect
modul dan ungkapan di atas jauh lebih lengkap, terutama jika tujuan Anda memfilter fungsi apa pun atau mendeteksi properti biasa dari suatu objek.sumber
types
modul. Saya sedang menguji sebuahmake_stemmer()
pabrik yang kadang-kadang mengembalikan fungsi dan kadang-kadangStemmer
instance yang bisa dipanggil , dan saya perlu mendeteksi perbedaannya.Coba gunakan
callable(x)
.sumber
Jika Anda telah belajar
C++
, Anda harus terbiasa dengan ,function object
ataufunctor
berarti benda apa pun yang bisabe called as if it is a function
.Dalam C ++,
an ordinary function
adalah objek fungsi, dan begitu juga pointer fungsi; lebih umum, begitu juga objek kelas yang mendefinisikanoperator()
. Dalam C ++ 11 dan lebih besar,the lambda expression
adalahfunctor
juga.Kesamaan, dalam Python, itu
functors
semuacallable
.An ordinary function
bisa dipanggil,a lambda expression
bisa dipanggil,functional.partial
bisa dipanggil, contohclass with a __call__() method
bisa dipanggil.Oke, kembali ke pertanyaan:
I have a variable, x, and I want to know whether it is pointing to a function or not.
Lalu saya melakukan percobaan menggunakan kode itu:
Saya menggambar tabel jenis functor yang bisa dipanggil menggunakan data.
seperti:
sumber
Sebagai jawaban yang diterima, John Feminella menyatakan bahwa:
Meskipun, ada dua lib untuk membedakan fungsi secara ketat, saya menggambar tabel sebanding yang lengkap:
8.9. types - Penciptaan tipe dinamis dan nama untuk tipe bawaan - Dokumentasi Python 3.7.0
30.13. inspect - Periksa objek langsung - Dokumentasi Python 3.7.0
"Bebek mengetik" adalah solusi yang lebih disukai untuk tujuan umum:
Adapun fungsi builtins
Ketika melangkah satu langkah lagi untuk memeriksa apakah fungsi builtin atau fungsi yang ditentukan pengguna
Tentukan apakah
builtin function
Ringkasan
Dipekerjakan
callable
untuk tipe bebek memeriksa fungsi,Gunakan
types.BuiltinFunctionType
jika Anda memiliki permintaan lebih lanjut yang ditentukan.sumber
Fungsi hanyalah kelas dengan
__call__
metode, jadi Anda bisa melakukannyaSebagai contoh:
Itu adalah cara "terbaik" untuk melakukannya, tetapi tergantung pada mengapa Anda perlu tahu apakah itu dapat dipanggil atau dicatat, Anda bisa memasukkannya ke dalam blok try / execpt:
Ini bisa diperdebatkan jika coba / kecuali lebih Python'y daripada melakukan
if hasattr(x, '__call__'): x()
.. Saya akan mengatakanhasattr
lebih akurat, karena Anda tidak sengaja menangkap TypeError yang salah, misalnya:sumber
Berikut beberapa cara lain:
Inilah cara saya menemukan yang kedua:
sumber
Alih-alih memeriksa
'__call__'
(yang tidak eksklusif untuk fungsi), Anda dapat memeriksa apakah fungsi yang ditetapkan pengguna memiliki atributfunc_name
,func_doc
dll ini tidak bekerja untuk metode.Cara lain untuk memeriksa adalah menggunakan
isfunction()
metode dariinspect
modul.Untuk memeriksa apakah suatu objek adalah metode, gunakan
inspect.ismethod()
sumber
Karena kelas juga memiliki
__call__
metode, saya merekomendasikan solusi lain:sumber
hasattr(obj, '__call__')
ambigu.Perhatikan bahwa kelas Python juga bisa dipanggil.
Untuk mendapatkan fungsi (dan fungsi, maksud kami adalah fungsi standar dan lambdas) gunakan:
sumber
Apa pun fungsi adalah kelas sehingga Anda dapat mengambil nama kelas instance x dan membandingkan:
sumber
Solusi yang menggunakan
hasattr(obj, '__call__')
dancallable(.)
disebutkan dalam beberapa jawaban memiliki kelemahan utama: keduanya juga kembaliTrue
untuk kelas dan contoh kelas dengan__call__()
metode. Misalnya.Salah satu cara yang tepat untuk memeriksa apakah suatu objek adalah fungsi yang ditentukan pengguna (dan tidak lain adalah itu) adalah dengan menggunakan
isfunction(.)
:Jika Anda perlu memeriksa jenis lain, lihat inspect - Periksa objek langsung .
sumber
Pemeriksa Fungsi Tepat
callable adalah solusi yang sangat bagus. Namun, saya ingin memperlakukan ini dengan cara yang berlawanan dari John Feminella. Alih-alih memperlakukannya seperti pepatah ini:
Kami akan memperlakukannya seperti ini:
Bagaimana Kami Menerapkannya
Modul 'types' memiliki banyak kelas untuk mendeteksi fungsi-fungsi, tipe-tipe yang paling berguna. Tipe Function , tetapi ada juga banyak yang lain, seperti tipe metode, tipe bawaan , dan tipe lambda. Kami juga akan menganggap objek 'functools.partial' sebagai fungsi.
Cara sederhana kita memeriksa apakah itu suatu fungsi adalah dengan menggunakan kondisi isinstance pada semua jenis ini. Sebelumnya, saya ingin membuat kelas dasar yang mewarisi dari semua di atas, tetapi saya tidak dapat melakukan itu, karena Python tidak mengizinkan kita mewarisi dari beberapa kelas di atas.
Berikut adalah tabel kelas apa yang dapat mengklasifikasikan fungsi apa:
Di atas tabel fungsi oleh kinght- 金
Kode Yang Melakukannya
Sekarang, ini adalah kode yang melakukan semua pekerjaan yang kami jelaskan dari atas.
Yang salah adalah is_function (parsial), karena itu adalah kelas, bukan fungsi, dan ini persis fungsi, bukan kelas. Ini adalah preview untuk Anda coba kode dari.
Kesimpulan
callable (obj) adalah metode yang disukai untuk memeriksa apakah suatu objek adalah fungsi jika Anda ingin pergi dengan mengetik bebek di atas absolut .
Fungsi is_function (obj) kustom kami , mungkin dengan beberapa pengeditan adalah metode yang disukai untuk memeriksa apakah suatu objek adalah fungsi jika Anda tidak menghitung instance kelas yang dapat dipanggil sebagai fungsi, tetapi hanya fungsi yang didefinisikan built-in , atau dengan lambda , def , atau sebagian .
Dan saya pikir itu membungkus semuanya. Semoga harimu menyenangkan!
sumber
Dalam Python3 saya datang dengan
type (f) == type (lambda x:x)
yang menghasilkanTrue
iff
adalah fungsi danFalse
jika tidak. Tapi saya rasa saya lebih sukaisinstance (f, types.FunctionType)
, yang terasa kurang ad hoc. Saya ingin melakukannyatype (f) is function
, tetapi itu tidak berhasil.sumber
Mengikuti balasan sebelumnya, saya datang dengan ini:
sumber
Anda bisa mencoba ini:
atau bahkan sesuatu yang lebih aneh:
sumber
Jika kode akan melanjutkan untuk melakukan panggilan jika nilainya dapat dipanggil, cukup lakukan panggilan dan tangkap
TypeError
.sumber
x
.Berikut ini adalah "cara ulang" untuk memeriksanya. Juga bekerja dengan lambda.
sumber
Ini bekerja untuk saya:
sumber
"<type 'function'>"
, untuk integer, saya dapatkan"<type 'int'>"
, jadi saya tidak melihat cara kerjanya untuk Anda: /open
dianggap sebagai fungsi?str(type(open))
memberi<class 'builtin_function_or_method'>
dalam Python 3.