2010-02-10 4 views
8

In Python ist es möglich, den obigen Code ohne eine Ausnahme zu haben?Ist es möglich, eine Funktion ohne Argumente zu deklarieren, aber dann einige Argumente an diese Funktion zu übergeben, ohne eine Ausnahme auszulösen?

Normalerweise in PHP unter einigen Umständen ich eine Funktion ohne Parameter starten und dann die Parameter innerhalb der Funktion abrufen.

In der Praxis möchte ich keine Argumente in myfunc deklarieren und dann einige Argumente übergeben. Die einzige Lösung, die ich gefunden habe, ist myfunc(*arg). Gibt es andere Methoden?

+9

Warum ist 'myfunc (* arg)' nicht gut genug? – interjay

+3

Ich vermute, yuri kennt (noch) nichts über * arg – Dana

+0

Die Implementierung muss myfunc ein Callback sein, der an eine andere Funktion übergeben wird, die versucht, sie in einem Listenverständnis aufzurufen und Argumente zu übergeben. Also habe ich keine Kontrolle über die Callback-Implementierung und der Benutzer kann absichtlich die '* args' nicht weglassen (In dem Code kümmere ich mich um dieses Ereignis) – yuri

Antwort

10
>>> def myFunc(*args, **kwargs): 
... # This function accepts arbitary arguments: 
... # Keywords arguments are available in the kwargs dict; 
... # Regular arguments are in the args tuple. 
... # (This behaviour is dictated by the stars, not by 
... # the name of the formal parameters.) 
... print args, kwargs 
... 
>>> myFunc() 
() {} 
>>> myFunc(2) 
(2,) {} 
>>> myFunc(2,5) 
(2, 5) {} 
>>> myFunc(b = 3) 
() {'b': 3} 
>>> import dis 
>>> dis.dis(myFunc) 
    1   0 LOAD_FAST    0 (args) 
       3 PRINT_ITEM 
       4 LOAD_FAST    1 (kwargs) 
       7 PRINT_ITEM 
       8 PRINT_NEWLINE 
       9 LOAD_CONST    0 (None) 
      12 RETURN_VALUE 

Und tatsächlich die Frage zu beantworten: Nein, ich glaube nicht, gibt es andere Möglichkeiten.

Der Hauptgrund ist ziemlich einfach: C Python ist Stack-basiert. Eine Funktion, für die keine Parameter benötigt werden, hat keinen Platz auf dem Stack zugewiesen (myFunc, stattdessen hat sie an Position 0 und 1). (siehe Kommentare)

Ein weiterer Punkt ist, wie würden Sie sonst auf die Parameter zugreifen?

+2

Der Stack-Kommentar ist neben dem Punkt. Python ist stackbasiert, aber Argumentübergabe (und Parsing) ist nicht (Argumente sind immer ein einzelnes Element auf dem Stack, auch wenn es keine Argumente gibt.) Der Grund, warum Python Argumente nicht ignoriert, liegt darin, dass es Fehler verbergen würde **. –

+0

Es ist in der Tat durchaus möglich, dass ich missverstanden habe, was dis sagt mir :) – badp

4

Sicher kann!

können Sie Variablenlisten Längenparameter wie so definieren:

def foo(*args): 
    print len(args) 

args ist ein Tupel Ihrer Parameter so aufrufen:

foo(1,2) 

gibt Ihnen die Tupel (1, 2) in Ihrer Funktion .

+0

'args' wird eigentlich ein Tupel sein. –

+0

Oh ja! Fest! – Dana

11

Es gibt zwei Möglichkeiten args in

nach Reihenfolge

>>> def myfunc(*args): 
... print "args", args 
... 
>>> myfunc("param") 
args ('param',) 

nach Stichwort

>>> def myfunc(**kw): 
... print "kw", kw 
... 
>>> myfunc(param="param") 
kw {'param': 'param'} 

Und Sie können eine Kombination von

passieren verwenden
>>> def myfunc(*args, **kw): 
... print "args", args 
... print "kw", kw 
... 
>>> myfunc("param") 
args ('param',) 
kw {} 
>>> 
>>> myfunc(param="param") 
args() 
kw {'param': 'param'} 
>>> 
>>> myfunc("param", anotherparam="anotherparam") 
args ('param',) 
kw {'anotherparam': 'anotherparam'} 
1

Hier ist eine Funktion Dekorateur ich nur das zu tun, schrieb zusammen mit einem Beispiel für die Nutzung:

def IgnoreExtraArguments(f): 
    import types 
    c = f.func_code 
    if c.co_flags & 0x04 or c.co_flags&0x08: 
     raise ValueError('function already accepts optional arguments') 
    newc = types.CodeType(c.co_argcount, 
        c.co_nlocals, 
        c.co_stacksize, 
        c.co_flags | 0x04 | 0x08, 
        c.co_code, 
        c.co_consts, 
        c.co_names, 
        c.co_varnames+('_ignore_args','_ignore_kwargs'), 
        c.co_filename, 
        c.co_name, 
        c.co_firstlineno, 
        c.co_lnotab, 
        c.co_freevars, 
        c.co_cellvars) 
    f.func_code = newc 
    return f 

if __name__ == "__main__": 
    def f(x,y): 
     print x+y 

    g = IgnoreExtraArguments(f) 
    g(2,4) 
    g(2,5,'banana') 

    class C(object): 
     @IgnoreExtraArguments 
     def m(self,x,y): 
      print x-y 

    a=C() 
    a.m(3,5) 
    a.m(3,6,'apple') 
Verwandte Themen