2008-11-13 36 views
231

Chính xác thì *args**kwargs là gì?Ý nghĩa của * args và ** kwargs là gì?

Theo tài liệu Python, từ những gì nó có vẻ, nó vượt qua trong một loạt các đối số.

def foo(hello, *args): 
    print hello 

    for each in args: 
     print each 

if __name__ == '__main__': 
    foo("LOVE", ["lol", "lololol"]) 

này in ra:

LOVE 
['lol', 'lololol'] 

Làm thế nào để bạn có hiệu quả sử dụng chúng?

+13

Chỉ là một cú đánh xấu trên Giờ và Kilo -Watt Giờ. – Mostlyharmless

+6

Bài viết này có thể rất hữu ích cho sự hiểu biết sâu về chủ đề: http://agiliq.com/blog/2012/06/understanding-args-and-kwargs/ –

Trả lời

225

Đặt *args và/hoặc **kwargs làm các mục cuối cùng trong danh sách đối số của định nghĩa hàm cho phép chức năng chấp nhận số đối số và/hoặc đối số từ khóa tùy ý.

Ví dụ, nếu bạn muốn viết một hàm trả lại tổng của tất cả đối số của nó, dù có bao nhiêu bạn cung cấp, bạn có thể viết nó như thế này:

def my_sum(*args): 
    return sum(args) 

Đây có thể là thường được sử dụng trong lập trình hướng đối tượng, khi bạn ghi đè một hàm và muốn gọi hàm ban đầu với bất kỳ đối số nào mà người dùng truy cập.

Bạn không thực sự phải gọi chúng là argskwargs. Đó là *** làm điều kỳ diệu.

Tài liệu Python chính thức có a more in-depth look.

+5

Không có mồ hôi, bạn rất hoan nghênh. Tôi cũng bối rối một lúc. Nếu bạn đang đi sâu vào Python, tôi xin chân thành giới thiệu ‘Lập trình Python’ của Mark Lutz. –

+39

Có lẽ liên kết đến hướng dẫn giải thích điều này theo chiều sâu và cần được mọi người đọc: http://docs.python.org/tutorial/controlflow.html#more-on-defining-functions –

+1

@AliAfshar: Liên kết của bạn là tất cả Tôi cần, nên đã là câu trả lời của chính nó. Cảm ơn! – scorpiodawg

82

Ngoài ra, chúng tôi sử dụng chúng để quản lý kế thừa.

class Super(object): 
    def __init__(self, this, that): 
     self.this = this 
     self.that = that 

class Sub(Super): 
    def __init__(self, myStuff, *args, **kw): 
     super(Sub, self).__init__(*args, **kw) 
     self.myStuff= myStuff 

x= Super(2.7, 3.1) 
y= Sub("green", 7, 6) 

Cách này không thực sự biết (hoặc quan tâm) việc khởi tạo siêu lớp là gì. Nếu bạn nhận ra rằng bạn cần phải thay đổi lớp cha, bạn có thể sửa chữa mọi thứ mà không phải đổ mồ hôi các chi tiết trong mỗi phân lớp.

+6

Đây là một trong những câu trả lời hữu ích nhất mà tôi đã tìm thấy về cách sử dụng 'super'. Câu trả lời này là hơn 5 tuổi, nhưng tôi đoán đây vẫn là một cách tuyệt vời để sử dụng 'super' trong Python 2.X, đúng không? –

+0

Có, vẫn còn cách để làm điều đó. –

+0

Cảm ơn, nhưng nó sẽ là tuyệt vời nếu bạn có thể cung cấp một số ví dụ thực tế, tại sao và khi nào sử dụng nó. Trong ví dụ trên, điều gì sẽ xảy ra nếu tôi làm điều đó? – TaraGurung

63

Thông báo điều mát mẻ trong S.Lott's comment - bạn cũng có thể gọi chức năng với *mylist**mydict để giải nén vị trí và từ khóa đối số:

def foo(a, b, c, d): 
    print a, b, c, d 

l = [0, 1] 
d = {"d":3, "c":2} 

foo(*l, **d) 

Sẽ in: 0 1 2 3

+0

Bạn cũng có thể thực hiện '* mydict' (không phải' ** mylist'), nhưng kết quả sẽ hơi khác (và bất ngờ đối với một số). – Tadeck

+1

đơn giản, ngắn gọn và dễ làm theo ví dụ để minh họa điểm. Loại câu trả lời yêu thích của tôi! – NickO

+0

@Tadeck Bạn có thể thực hiện '* x' cho bất kỳ phép lặp nào và' ** y' cho bất kỳ loại ánh xạ nào. Kể từ khi một dict là cả một iterable và lập bản đồ bạn có thể làm một trong hai. Xem thêm http://stackoverflow.com/questions/8601268/python-class-that-acts-as-mapping-for-unpacking – augurar

24

Một sử dụng tốt cho *args**kwargs: bạn có thể định nghĩa các hàm "bắt tất cả" chung, điều này rất tốt cho các trình trang trí nơi bạn trả về một trình bao bọc thay vì hàm ban đầu.

Một ví dụ với một bộ nhớ đệm trang trí tầm thường:

import pickle, functools 
def cache(f): 
    _cache = {} 
    def wrapper(*args, **kwargs): 
    key = pickle.dumps((args, kwargs)) 
    if key not in _cache: 
     _cache[key] = f(*args, **kwargs) # call the wrapped function, save in cache 
    return _cache[key] # read value from cache 
    functools.update_wrapper(wrapper, f) # update wrapper's metadata 
    return wrapper 

import time 
@cache 
def foo(n): 
    time.sleep(2) 
    return n*2 

foo(10) # first call with parameter 10, sleeps 
foo(10) # returns immediately 
15

Chỉ cần làm rõ làm thế nào để giải nén các đối số, và chăm sóc các đối số mất tích, vv

def func(**keyword_args): 
    #-->keyword_args is a dictionary 
    print 'func:' 
    print keyword_args 
    if keyword_args.has_key('b'): print keyword_args['b'] 
    if keyword_args.has_key('c'): print keyword_args['c'] 

def func2(*positional_args): 
    #-->positional_args is a tuple 
    print 'func2:' 
    print positional_args 
    if len(positional_args) > 1: 
    print positional_args[1] 

def func3(*positional_args, **keyword_args): 
    #It is an error to switch the order ie. def func3(**keyword_args, *positional_args): 
    print 'func3:' 
    print positional_args 
    print keyword_args 

func(a='apple',b='banana') 
func(c='candle') 
func2('apple','banana')#It is an error to do func2(a='apple',b='banana') 
func3('apple','banana',a='apple',b='banana') 
func3('apple',b='banana')#It is an error to do func3(b='banana','apple')