2010-02-10 45 views
8

Trong trăn là nó có thể có mã trên mà không làm tăng một ngoại lệ?Có thể khai báo một hàm không có đối số nhưng sau đó chuyển một số đối số cho hàm đó mà không cần tăng ngoại lệ?

def myfunc(): 
    pass 

# TypeError myfunc() takes no arguments (1 given) 
myfunc('param') 

Thông thường trong php trong một số trường hợp tôi khởi động một hàm không có tham số và sau đó lấy các thông số bên trong hàm.

Trong thực tế, tôi không muốn khai báo các đối số trong myfunc và sau đó chuyển một số đối số cho nó. Giải pháp duy nhất tôi tìm thấy là myfunc(*arg). Có phương pháp nào khác không?

+9

Tại sao là 'myfunc (* arg) 'không đủ tốt? – interjay

+3

Tôi đoán yuri không (chưa biết) về * arg – Dana

+0

Việc thực hiện cần myfunc là một cuộc gọi lại được chuyển đến một hàm khác mà thử gọi nó trong một danh sách hiểu đi qua một đối số. Vì vậy, tôi không có quyền kiểm soát việc thực hiện gọi lại và người dùng không thể cố tình bỏ qua '* args' (trong mã tôi quan tâm đến sự kiện này) – yuri

Trả lời

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 

Và thực sự trả lời câu hỏi: không, tôi không tin có những cách khác.

Lý do chính khá đơn giản: C python là ngăn xếp dựa. Một hàm không yêu cầu tham số sẽ không có khoảng trống được phân bổ cho nó trên ngăn xếp (myFunc, thay vào đó, có chúng ở vị trí 0 và 1). (xem nhận xét)

Điểm bổ sung là, bạn sẽ truy cập thông số bằng cách nào?

+2

Nhận xét ngăn xếp nằm ngoài điểm. Python là dựa trên stack, nhưng đối số đi qua (và phân tích cú pháp) không phải là (đối số luôn là một mục duy nhất trên ngăn xếp, ngay cả khi không có đối số). Lý do Python không bỏ qua đối số là vì nó sẽ ẩn lỗi **. –

+0

Nó thực sự khá có thể tôi đang hiểu sai những gì dis nói với tôi :) – badp

4

Chắc chắn có thể!

Bạn có thể xác định danh sách tham số chiều dài thay đổi như sau:

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

args là một tuple các thông số của bạn để gọi:

foo(1,2) 

mang đến cho bạn tuple (1, 2) bên trong hàm của bạn .

+0

'args' sẽ thực sự là một tuple. –

+0

Ồ vâng! Đã sửa! – Dana

11

Có hai cách để vượt qua args trong

By Vị trí

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

By Từ khoá

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

Và bạn có thể sử dụng một sự kết hợp của cả hai

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

Đây là một trang trí chức năng tôi đã viết để làm điều đó, cùng với một ví dụ về việc sử dụng:

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') 
Các vấn đề liên quan