Python işlevinin bağımsız değişken sayısını nasıl bulabilirim?


163

Python işlevinin bağımsız değişken sayısını nasıl bulabilirim? Kaç tane normal argüman olduğunu ve kaç tane argüman olduğunu bilmem gerekiyor.

Misal:

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

Bu yöntemin 2 bağımsız değişkeni ve 1 adlı bağımsız değişkeni vardır.


43
soru tamamen garanti altındadır; olmasaydı (kaynağı her zaman okuyabildiğiniz için), inspectstandart kütüphane modülü için herhangi bir gerekçe olmazdı .
akış

Birçok dilde en az bir haksız özellik vardır. inspectO içinde belirli bir işlevi olsaydı bütün modül haksız olacağını söylemek haksızlık böylece modül, diğer özellikleri bir yeri vardır. Dahası, bu özelliğin nasıl yetersiz kullanılabileceğini görmek kolaydır. (Bkz. Stackoverflow.com/questions/741950 ). Bununla birlikte, özellikle dekoratörler ve işlev üzerinde çalışan diğer işlevler yazmak için yararlı bir özelliktir.
user1612868

Yanıtlar:


131

Daha önce kabul edilen cevap şu tarihten beri kullanımdan kaldırıldı :Python 3.0 . Kullanmak yerine inspect.getargspecşimdiSignature onun yerini sınıfı .

Fonksiyon için bir imza oluşturma yoluyla kolaydır signaturefonksiyonu :

from inspect import signature

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

sig = signature(someMethod)

Şimdi, parametrelerini hızlı bir şekilde görüntüleyerek görüntüleyebilirsiniz str:

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

veya öznitelik adlarının parametre nesneleriyle eşleştirilmesini de sağlayabilirsiniz sig.parameters.

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

Ayrıca, çağırabilir lenüzerinde sig.parametersde bu işlev gerektirir argümanların sayısını görmek için:

print(len(params))  # 3

Haritadaki her bir giriş paramsaslında hayatınızı kolaylaştıran başka özelliklere sahip bir Parameternesnedir . Örneğin, bir parametrenin yakalanması ve varsayılan değerinin görüntülenmesi artık aşağıdakilerle kolayca gerçekleştirilebilir:

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

benzer şekilde içerdiği nesnelerin geri kalanı için parameters.


Python gelince 2.xatan kullanıcılar, inspect.getargspec değil kaldırılan, dil yakında :-) olacaktır. SignatureSınıf mevcut değildir 2.xserisi ve olmayacaktır. Yani hala çalışman gerekiyor inspect.getargspec.

Eğer kodunuz varsa Python 2 ve 3 arasında geçiş gelince, arayüzünde dayanmasıdır getargspecPython 2'de ve geçiş signaturede 3çok zordur, değerli seçeneği var kullanmanın inspect.getfullargspec. Ayrıca, bir getargspecişlevin bağımsız değişkenlerini yakalamak ve ayrıca aşağıdakileri getargspecyapmayan bazı ek durumları ele almak için (tek bir çağrılabilir bağımsız değişken) ile benzer bir arabirim sunar :

from inspect import getfullargspec

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

args = getfullargspec(someMethod)

Gibi getargspec, getfullargspecbir döner NamedTupleparametreleri içeren.

print(args)
FullArgSpec(args=['self', 'arg1', 'kwarg1'], varargs=None, varkw=None, defaults=(None,), kwonlyargs=[], kwonlydefaults=None, annotations={})

1
@ GeorgSchölly hoş geldiniz. Bunun gibi popüler bir soruyu, ya kullanımdan kaldırılan ya da sağ sinsi ( co_argcountözellikte
gözetleyen

1
getfullargspecPython 2.x'te uygulanmadıysa, kullanmanız gerekirgetargspec
Peter Gibson

getargspecyerleşik işlevler üzerinde çalışmaz: getargspec(open)verir Bazı fikirler için bu cevabıTypeError: <built-in function open> is not a Python function görün ...
starfry

Son örnekte, bunu yaptığında print(args)sen alamadım defaults=(None,)almak defaults=None.
Seanny123

si dekorasyon sonrası dekore edilmiş bir fonksiyon için orijinal parametre sayısını almak için bir yol var ..?
Gulats

117
import inspect
inspect.getargspec(someMethod)

bkz modülü kontrol


5
Genellikle istediğiniz şeydir, ancak bu yerleşik işlevler için çalışmaz. Builtins için bu bilgi almak için tek yolu , çirkin ama yapılabilir dokümanlar dizesini ayrıştırmaktır .
Cerin

5
Bu Python 3'te kullanımdan kaldırılmıştır: docs.python.org/3/library/inspect.html#inspect.getargspec
noisecapella

Python 3'te kullanımdan kaldırılmamış bir çözüm var mı?
hlin117

1
Bağlantıyı takip ederseniz inspect.signature- docs.python.org/3/library/inspect.html#inspect.signature
coderforlife

Burada doktrin ayrıştırılmadan yerleşik işlevler için başka bir olası yaklaşım yayınladım: stackoverflow.com/questions/48567935/…
HelloWorld

31
someMethod.func_code.co_argcount

veya geçerli işlev adı belirlenmemişse:

import sys

sys._getframe().func_code.co_argcount

4
@elyase, yapmanız gerekenler: dir(someMethod)-> 'func_code'; Daha ileriye git: dir(someMethod.func_code)-> 'co_argcount'; dir()Bir nesnenin kullanılabilir yöntemlerini belirlemek için yerleşik nesneyi kullanabilirsiniz.

@elyase Ben de kibar davrandım, bu yüzden bunu buldum docs.python.org/2/library/inspect.html#types-and-members
rodripf

Python 3'ü desteklemek için:six.get_function_code(someMethod).co_argcount
noisecapella

8
@noisecapella ne zaman sen-ebilmek yapmak bir üçüncü taraf modülü gerek yoksome_method.__code__.co_argcount
vallentin

1
Genel olarak, olmamalıdır bunlar bakmak için fonksiyon nesnenin içindeki Bakmak. co_argcountkod nesnesinin değerlendirilmesi sırasında dahili olarak kullanılır. Söylemeye çalıştığım şey, bu özelliklerin bir sürümden diğerine değişmeyeceğine dair hiçbir garanti yok.
Dimitris Fasarakis Hilliard

16

inspect.getargspec ()

Bir işlevin bağımsız değişkenlerinin adlarını ve varsayılan değerlerini alın. Dört şeyden oluşan bir grup döndürülür: (args, varargs, varkw, default). args argüman adlarının bir listesidir (iç içe listeler içerebilir). varargs ve varkw, * ve ** bağımsız değişkenlerinin adları veya None'dır. varsayılanlar, varsayılan bağımsız değişken değerlerinin bir demetidir veya varsayılan bağımsız değişken yoksa Yok'tur; bu demet n elemente sahipse, argümanlarda listelenen son n elemente karşılık gelir.

2.6 sürümünde değiştirildi: Adlandırılmış bir ArgSpec grubunu (argümanlar, varargs, anahtar kelimeler, varsayılanlar) döndürür.

Bkz. Can-you-list-the-keyword-arguments-a-python-function-receives .


5

Yukarıdakilere ek olarak, çoğu zaman help () işlevinin gerçekten yardımcı olduğunu gördüm

Örneğin, aldığı argümanlarla ilgili tüm ayrıntıları verir.

help(<method>)

aşağıdakileri verir

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

İnsanların bir gönderi ile ilgili sorun hakkında yorum yapmaları, yalnızca eksi düğmesini tıklamaktan daha iyi olur.
Venu Murthy

2
helpişlevi sadece doktora dediklerini gösterir. Hatta sorudaki işlev tanımıyla çalışıp çalışmadığını test ettiniz mi?
0xc0de

@ 0xc0de - Test ettiniz mi? Çünkü aslında işe yarıyor. help()sadece docstring'den daha fazla tükürür - belgesiz kodda bile hala argspec'i yazdırır ve kodun nerede tanımlandığını söyler. Orijinal soruyu gönderen kişi, makine veya insan dostu bir cevaba ihtiyaç duyup duymadıkları net değildi. Sadece insan dostu olması gerekiyorsa help(), mükemmel yeterlidir.
ArtOfWarfare

@ArtOfWarfare hiç, şimdi ne olursa olsun ayrıştırmak zorunda kalacak değil help()döner ve denemek ve bulmak argsve kwargs.
Vallentin

5

Python 2 ve Python 3.6+ arasında taşınabilir bir şekilde yapmak isteyen insanlar için iyi haber: kullanım inspect.getfullargspec() yöntemi. Hem Python 2.x hem de 3.6+ sürümlerinde çalışır

Jim Fasarakis Hilliard ve diğerlerinin de belirttiği gibi, eskiden şöyle olurdu:
1. Python 2.x'te: kullanın inspect.getargspec()
2. Python 3.x'te: imzayı kullanın getargspec()ve getfullargspec()kullanımdan kaldırıldı.

Ancak, Python 3.6'dan başlayarak (popüler talep üzerine?), İşler daha iyi hale geldi:

Python 3 dokümantasyon sayfasından :

inspect.getfullargspec (fonk)

3.6 sürümünde değiştirildi : Bu yöntem daha önce signature()Python 3.5 lehine kullanımdan kaldırılmıştı , ancak eski getargspec()API'dan ayrılan tek kaynaklı Python 2/3 kodu için açıkça desteklenen standart bir arayüzü geri yüklemek için bu karar tersine çevrildi .


3

ihtiyaçlarınızı karşılamak için inspect.getargspec ()

from inspect import getargspec

def func(a, b):
    pass
print len(getargspec(func).args)

1
Stack Overflow'a hoş geldiniz! Lütfen sadece kaynak koduyla cevap vermeyin. Çözümünüzün nasıl çalıştığı hakkında güzel bir açıklama sağlamaya çalışın. Bkz: İyi bir cevabı nasıl yazarım? . Thanks
sɐunıɔ ןɐ qɐp

2

Diğer cevapların önerdiği getargspecgibi, sorgulanan şey aslında bir işlev olduğu sürece iyi çalışır. O çalışmıyor yerleşik gibi fonksiyonlar open, lenvb, ve bu gibi durumlarda bir istisna durumu:

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

Aşağıdaki işlev ( bu yanıttan esinlenerek ) bir geçici çözüm gösterir. Bekleyen bağımsız değişken sayısını döndürür 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

Fikir, işlev spesifikasyonunu __doc__dizeden ayrıştırmaktır . Açıkçası bu, söz konusu dizenin biçimine dayanmaktadır, bu yüzden pek sağlam değildir!


2

func.__code__.co_argcountÖNCE size herhangi bir argüman sayısı verir *args

func.__kwdefaults__Size bir dicti verir anahtar kelime argümanlar SONRA *args

func.__code__.co_kwonlyargcount eşittir len(func.__kwdefaults__)

func.__defaults__size daha önce görünen isteğe bağlı bağımsız değişkenlerin değerlerini verir *args

İşte basit örnek:

illüstrasyon

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

0

İçinde:

import inspect 

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

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

Dışarı:

4


Not: Eğer xyz X sınıfı içinde olmasaydı ve "ben" ve sadece "a, b, c" olmasaydı, 3 basardı.

3.5'in altında piton için, değiştirmek isteyebilir inspect.getfullargspectarafından inspect.getargspecyukarıdaki kodda.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.