Bagaimana saya bisa menemukan jumlah argumen dari fungsi Python?

163

Bagaimana saya bisa menemukan jumlah argumen dari fungsi Python? Saya perlu tahu berapa banyak argumen normal yang dimilikinya dan berapa banyak argumen yang dinamai.

Contoh:

def someMethod(self, arg1, kwarg1=None):
    pass

Metode ini memiliki 2 argumen dan 1 argumen bernama.

Georg Schölly
sumber
43
pertanyaan dijamin sepenuhnya; jika tidak (karena Anda selalu dapat membaca sumbernya), tidak akan ada pembenaran untuk inspectmodul perpustakaan standar.
mengalir
Banyak bahasa menerapkan setidaknya satu fitur yang tidak dapat dibenarkan. The inspectmodul memiliki banyak fitur lainnya, sehingga tidak adil untuk mengatakan bahwa seluruh modul akan dibenarkan jika salah satu fungsi tertentu di itu. Selain itu, mudah untuk melihat bagaimana fitur ini dapat digunakan dengan buruk. (Lihat stackoverflow.com/questions/741950 ). Yang mengatakan, itu adalah fitur yang berguna, terutama untuk menulis dekorator dan fungsi lain yang beroperasi pada fungsi.
user1612868

Jawaban:

130

Jawaban yang diterima sebelumnya telah ditinggalkan pada Python 3.0. Alih-alih menggunakan inspect.getargspecAnda sekarang harus memilih Signaturekelas yang menggantikannya.

Membuat tanda tangan untuk fungsi itu mudah melalui signaturefungsi :

from inspect import signature

def someMethod(self, arg1, kwarg1=None):
    pass

sig = signature(someMethod)

Sekarang, Anda dapat melihat parameternya dengan cepat dengan strmemasukkannya:

str(sig)  # returns: '(self, arg1, kwarg1=None)'

atau Anda juga bisa mendapatkan pemetaan nama atribut ke objek parameter via sig.parameters.

params = sig.parameters 
print(params['kwarg1']) # prints: kwarg1=20

Selain itu, Anda dapat menghubungi lendi sig.parametersuntuk juga melihat jumlah argumen fungsi ini membutuhkan:

print(len(params))  # 3

Setiap entri dalam paramspemetaan sebenarnya adalah Parameterobjek yang memiliki atribut lebih lanjut yang membuat hidup Anda lebih mudah. Misalnya, mengambil parameter dan melihat nilai defaultnya sekarang dengan mudah dilakukan dengan:

kwarg1 = params['kwarg1']
kwarg1.default # returns: None

sama untuk sisa benda yang ada di parameters.


Sedangkan untuk 2.xpengguna Python , sementara inspect.getargspec tidak ditinggalkan, bahasa akan segera menjadi :-). The Signaturekelas tidak tersedia di 2.xseri dan tidak akan. Jadi, Anda masih perlu bekerja sama inspect.getargspec.

Adapun transisi antara Python 2 dan 3, jika Anda memiliki kode yang bergantung pada antarmuka getargspecdi Python 2 dan beralih ke signaturedalam 3terlalu sulit, Anda memiliki opsi berharga untuk menggunakan inspect.getfullargspec. Ia menawarkan antarmuka yang mirip dengan getargspec(satu argumen yang bisa dipanggil) untuk mendapatkan argumen dari suatu fungsi sambil juga menangani beberapa kasus tambahan yang getargspectidak:

from inspect import getfullargspec

def someMethod(self, arg1, kwarg1=None):
    pass

args = getfullargspec(someMethod)

Seperti halnya getargspec, getfullargspecmengembalikan NamedTupleyang berisi argumen.

print(args)
FullArgSpec(args=['self', 'arg1', 'kwarg1'], varargs=None, varkw=None, defaults=(None,), kwonlyargs=[], kwonlydefaults=None, annotations={})
Dimitris Fasarakis Hilliard
sumber
1
Sama-sama @ GeorgSchölly. Saya terkejut dengan pertanyaan populer seperti ini yang menawarkan solusi baik yang sudah usang atau licik ke kanan (mengintip dalam co_argcountatribut.)
Dimitris Fasarakis Hilliard
1
getfullargspectidak diimplementasikan dalam Python 2.x, Anda perlu menggunakangetargspec
Peter Gibson
getargspectidak bekerja pada fungsi getargspec(open)TypeError: <built-in function open> is not a Python function
bawaan
Dalam contoh terakhir Anda, ketika Anda melakukannya print(args)Anda tidak mendapatkan defaults=(None,)Anda defaults=None.
Seanny123
si ada cara untuk mendapatkan jumlah parameter asli untuk suatu fungsi yang telah dihiasi posting dekorasi ..?
Gulats
117
import inspect
inspect.getargspec(someMethod)

lihat modul inspeksi

Jochen Ritzel
sumber
5
Umumnya yang Anda inginkan, tetapi ini tidak berfungsi untuk fungsi bawaan. Satu-satunya cara untuk mengetahui untuk mendapatkan info ini untuk builtin adalah dengan menguraikan string doc mereka , yang jelek tapi bisa dilakukan.
Cerin
5
Ini tidak digunakan lagi dalam Python 3: docs.python.org/3/library/inspect.html#inspect.getargspec
noisecapella
Apakah ada solusi yang tidak usang dalam Python 3?
hlin117
1
Jika Anda mengikuti tautan, Anda akan melihat bahwa itu merekomendasikan penggunaan inspect.signature- docs.python.org/3/library/inspect.html#inspect.signature
coderforlife
Saya memposting pendekatan lain yang mungkin untuk fungsi builtin tanpa menguraikan dokumen di sini: stackoverflow.com/questions/48567935/…
HelloWorld
31
someMethod.func_code.co_argcount

atau, jika nama fungsi saat ini tidak ditentukan:

import sys

sys._getframe().func_code.co_argcount
miaever
sumber
4
@elyase, lakukan saja: dir(someMethod)-> 'func_code'; Lebih jauh: dir(someMethod.func_code)-> 'co_argcount'; Anda dapat menggunakan bawaan dir()untuk menentukan metode yang tersedia dari suatu objek.
@elyase saya juga berani, jadi saya menemukan ini docs.python.org/2/library/inspect.html#types-and-members
rodripf
Untuk mendukung Python 3:six.get_function_code(someMethod).co_argcount
noisecapella
8
@noisecapella tidak perlu untuk modul pihak ketiga, ketika Anda bisa melakukannyasome_method.__code__.co_argcount
vallentin
1
Secara umum, Anda tidak harus mengintip ke dalam objek fungsi untuk melihat hal-hal ini. co_argcountdigunakan secara internal selama evaluasi objek kode. Yang ingin saya katakan adalah, benar-benar tidak ada jaminan bahwa atribut ini tidak akan berubah dari satu rilis ke rilis lainnya.
Dimitris Fasarakis Hilliard
16

inspect.getargspec ()

Dapatkan nama dan nilai default dari argumen fungsi. Sebuah tuple dari empat hal dikembalikan: (args, varargs, varkw, defaults). args adalah daftar nama argumen (mungkin berisi daftar bersarang). varargs dan varkw adalah nama argumen * dan ** atau Tidak Ada. default adalah tuple dari nilai argumen default atau None jika tidak ada argumen default; jika tuple ini memiliki n elemen, mereka bersesuaian dengan n elemen terakhir yang tercantum dalam args.

Berubah dalam versi 2.6: Mengembalikan tuple bernama ArgSpec (args, varargs, kata kunci, default).

Lihat can-you-list-the-keyword-argumen-a-python-function-accept .

Gimel
sumber
5

Menambahkan ke atas, saya juga melihat bahwa sebagian besar kali help () function sangat membantu

Misalnya, memberikan semua detail tentang argumen yang diperlukan.

help(<method>)

berikan di bawah ini

method(self, **kwargs) method of apiclient.discovery.Resource instance
Retrieves a report which is a collection of properties / statistics for a specific customer.

Args:
  date: string, Represents the date in yyyy-mm-dd format for which the data is to be fetched. (required)
  pageToken: string, Token to specify next page.
  parameters: string, Represents the application name, parameter name pairs to fetch in csv as app_name1:param_name1, app_name2:param_name2.

Returns:
  An object of the form:

    { # JSON template for a collection of usage reports.
    "nextPageToken": "A String", # Token for retrieving the next page
    "kind": "admin#reports#usageReports", # Th
Venu Murthy
sumber
Akan lebih baik bagi orang-orang untuk meninggalkan komentar tentang apa yang salah dengan sebuah posting daripada hanya mengklik tombol minus.
Venu Murthy
2
helpfungsi hanya menunjukkan apa yang dikatakan docstring. Pernahkah Anda menguji apakah itu berfungsi dengan definisi fungsi dalam pertanyaan?
0xc0de
@ 0xc0de - Sudahkah Anda mengujinya? Karena itu benar-benar berfungsi. help()meludahkan lebih dari sekedar docstring - bahkan pada kode tidak berdokumen itu masih mencetak argspec dan memberi tahu Anda di mana kode itu didefinisikan. Orang yang memposting pertanyaan asli tidak jelas apakah mereka membutuhkan jawaban yang ramah mesin atau manusia. Jika hanya perlu ramah manusia, itu help()sudah cukup memadai.
ArtOfWarfare
@ ArtOfWarfare sama sekali tidak, karena sekarang Anda harus menguraikan help()kembali apa pun , dan mencoba dan menemukan argsdan kwargs.
vallentin
5

Kabar baik bagi orang-orang yang ingin melakukan ini dengan cara yang portabel antara Python 2 dan Python 3.6+: gunakan inspect.getfullargspec() metode. Ia bekerja di kedua Python 2.x dan 3.6+

Seperti yang ditunjukkan oleh Jim Fasarakis Hilliard dan yang lainnya, dulunya seperti ini:
1. Dalam Python 2.x: gunakan inspect.getargspec()
2. Dalam Python 3.x: gunakan tanda tangan, seperti getargspec()dan getfullargspec()sudah ditinggalkan.

Namun, mulai Python 3.6 (berdasarkan permintaan populer?), Banyak hal telah berubah menjadi lebih baik:

Dari halaman dokumentasi Python 3 :

inspect.getfullargspec (func)

Berubah dalam versi 3.6 : Metode ini sebelumnya didokumentasikan sebagai tidak digunakan lagi dalam signature()Python 3.5, tetapi keputusan itu telah dibalik untuk mengembalikan antarmuka standar yang didukung jelas untuk kode Python 2/3 sumber tunggal yang bermigrasi dari getargspec()API legacy .

HAltos
sumber
3

inspect.getargspec () untuk memenuhi kebutuhan Anda

from inspect import getargspec

def func(a, b):
    pass
print len(getargspec(func).args)
Eds_k
sumber
1
Selamat Datang di Stack Overflow! Tolong jangan jawab hanya dengan kode sumber. Cobalah untuk memberikan deskripsi yang bagus tentang cara kerja solusi Anda. Lihat: Bagaimana saya menulis jawaban yang baik? . Terima kasih
sɐunıɔ ןɐ qɐp
2

Seperti jawaban lain menyarankan, getargspecberfungsi dengan baik selama hal yang ditanyakan sebenarnya adalah fungsi. Ini tidak bekerja untuk built-in fungsi seperti open, len, dll, dan akan melemparkan pengecualian dalam kasus seperti:

TypeError: <built-in function open> is not a Python function

Fungsi di bawah ini (terinspirasi oleh jawaban ini ) menunjukkan solusi. Ini mengembalikan jumlah args yang diharapkan oleh f:

from inspect import isfunction, getargspec
def num_args(f):
  if isfunction(f):
    return len(getargspec(f).args)
  else:
    spec = f.__doc__.split('\n')[0]
    args = spec[spec.find('(')+1:spec.find(')')]
    return args.count(',')+1 if args else 0

Idenya adalah untuk mengurai spesifikasi fungsi dari __doc__string. Jelas ini bergantung pada format kata string sehingga hampir tidak kuat!

starfry
sumber
2

func.__code__.co_argcountmemberikan jumlah setiap argumen SEBELUM *args

func.__kwdefaults__memberi Anda argumen kata kunci SETELAH *args

func.__code__.co_kwonlyargcount adalah sama dengan len(func.__kwdefaults__)

func.__defaults__memberi Anda nilai argumen opsional yang muncul sebelumnya *args

Inilah ilustrasi sederhana:

ilustrasi

>>> def a(b, c, d, e, f=1, g=3, h=None, *i, j=2, k=3, **L):
    pass

>>> a.__code__.co_argcount
7
>>> a.__defaults__
(1, 3, None)
>>> len(a.__defaults__)
3
>>> 
>>> 
>>> a.__kwdefaults__
{'j': 2, 'k': 3}
>>> len(a.__kwdefaults__)
2
>>> a.__code__.co_kwonlyargcount
2
Hzzkygcs
sumber
0

Di:

import inspect 

class X:
    def xyz(self, a, b, c): 
        return 

print(len(inspect.getfullargspec(X.xyz).args))

Di luar:

4


Catatan: Jika xyz tidak berada di dalam kelas X dan tidak memiliki "diri" dan hanya "a, b, c", maka itu akan dicetak 3.

Untuk python di bawah 3.5, Anda mungkin ingin mengganti inspect.getfullargspecdengan inspect.getargspeckode di atas.

Guillaume Chevalier
sumber