Hva er høyeste antall argumenter i en Python-funksjon?

stemmer
27

Det er noe allment kjent at Python funksjoner kan ha maksimalt 256 argumenter. Det jeg er nysgjerrig på å vite er om denne grensen gjelder *argsog **kwargsnår de er rullet ut på følgende måte:

items = [1,2,3,4,5,6]

def do_something(*items):
    pass

Jeg spør fordi, hypotetisk, kan det være tilfeller der en liste større enn 256 elementer blir rullet ut som et sett av *argseller **kwargs.

Publisert på 03/04/2009 klokken 15:32
kilden bruker
På andre språk...                            


6 svar

stemmer
0

Jeg prøvde for en liste over 4000 gjenstander, og det fungerte. Så jeg tipper at det vil fungere for større verdier også.

Svarte 03/04/2009 kl. 15:35
kilden bruker

stemmer
21

WFM

>>> fstr = 'def f(%s): pass' % (', '.join(['arg%d' % i for i in range(5000)]))
>>> exec(fstr)
>>> f
<function f at 0x829bae4>

Oppdatering: som Brian lagt merke til, er grensen på kall side:

>>> exec 'f(' + ','.join(str(i) for i in range(5000)) + ')'

Traceback (most recent call last):
  File "<pyshell#63>", line 1, in <module>
    exec 'f(' + ','.join(str(i) for i in range(5000)) + ')'
  File "<string>", line 1
SyntaxError: more than 255 arguments (<string>, line 1)

på den annen side dette fungerer:

>>> f(*range(5000))
>>> 

Konklusjon: nei, det gjelder ikke rullet argumenter.

Svarte 03/04/2009 kl. 15:44
kilden bruker

stemmer
1

for ** kwargs, hvis jeg husker godt, er dette en ordbok. Det har derfor omtrent ingen grenser.

for * args, jeg er ikke så sikker, men jeg tror det er en tuppel eller en liste, så det har også omtrent ingen grenser.

På ingen grenser, mener jeg bortsett fra kanskje minnegrensen.

Svarte 03/04/2009 kl. 15:46
kilden bruker

stemmer
5

Dette synes å være en begrensning i kompilering kilden, så vil trolig eksisterer bare for argumenter som sendes direkte, ikke i * args eller ** kwargs.

Den aktuelle koden kan bli funnet i ast.c :

if (nargs + nkeywords + ngens > 255) {
  ast_error(n, "more than 255 arguments");
  return NULL;
}

Men merk at dette er i ast_for_call, og så bare applys til kallet side. dvs f(a,b,c,d,e...), snarere enn definisjonen, men det vil telle både posisjon (a,b,c,d)og keyword (a=1, b=2, c=3)stil parametre. Faktiske *argsog **kwargsparametere ser ut som de skal bare telle som ett argument for disse formålene på kallet side.

Svarte 03/04/2009 kl. 16:45
kilden bruker

stemmer
21

Grensen er på grunn av hvordan de kompilerte bytekode behandler kalle en funksjon med posisjons argumenter og / eller søkeord argumenter.

Den bytekode op av interesse er CALL_FUNCTIONsom bærer en op_argsom er 4 byte lang, men på de to minst signifikante byte brukes. Av disse, den mest signifikante byte representerer antall søkeord argumenter på stakken og minst signifikante byte antall posisjonelle argumenter på stakken. Derfor kan du på de fleste 0xFF == 255søkeord argumenter eller 0xFF == 255posisjons argumenter.

Denne grensen gjelder ikke for *argsog **kwargsfordi samtaler med at grammatikk bruke Bytecode ops CALL_FUNCTION_VAR, CALL_FUNCTION_KWog CALL_FUNCTION_VAR_KWavhengig av signaturen. For disse opcodes, stabelen består av en iterable for *argsog en dictfor den **kwargs. Disse elementene blir sendt direkte til mottakeren som unrolls dem etter behov.

Svarte 19/01/2012 kl. 19:36
kilden bruker

stemmer
8

I versjoner før Python 3.7, har CPython en grense på 255 eksplisitt vedtatt argumenter i en samtale:

>>> def f(*args, **kwargs): pass
...
>>> exec("f({})".format(', '.join(map(str, range(256)))))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
SyntaxError: more than 255 arguments

Denne begrensningen er på plass, fordi inntil Python 3,5, den CALL_FUNCTIONopkode overbelastet opkode argument for å kode både antall posisjonelle og søkeord argumenter på stabelen, som hver er kodet i en enkelt byte.

Denne begrensningen er fjernet i den kommende Python 3.7 utgivelsen, se problemet # 27213 og problemet # 12844 ; # 27213 omarbeidet CALL_FUNCTION*familien av opcodes til ytelse og enkelhet (del på 3,6), og frigjør den opkode argument for å kode bare en enkelt argument teller, og # 12844 fjernet kompilering tidskontrollen som hindret kode med flere argumenter blir kompilert.

I 3.7, med EXTENDED_ARG()opcode , er det nå ingen begrensning i det hele tatt på hvor mange argumenter du kan passere i å bruke eksplisitte argumenter, lagre hvor mange som kan settes på stakken (så nå bundet av hukommelsen):

>>> import sys
>>> sys.version_info
sys.version_info(major=3, minor=7, micro=0, releaselevel='alpha', serial=2)
>>> def f(*args, **kwargs): pass
...
>>> exec("f({})".format(', '.join(map(str, range(256)))))
>>> exec("f({})".format(', '.join(map(str, range(2 ** 16)))))

Gjør oppmerksom på at lister, tupler og ordbøker er begrenset til sys.maxsizeelementer, så hvis det heter funksjonen bruker *argsog / eller **kwargsfange-alle parametere så de er begrenset.

For *argsog **kwargssamtale syntaks (ekspanderende argumenter) er det ingen andre enn de samme grensene sys.maxintstørrelsesgrenser for Python standard typer.

Svarte 01/01/2018 kl. 16:46
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more