Pertanyaan * args dan ** kwargs? [duplikat]


Pertanyaan ini sudah memiliki jawaban di sini:

Jadi saya mengalami kesulitan dengan konsep *args dan **kwargs.

Sejauh ini saya telah belajar bahwa:

  • *args = daftar argumen - sebagai argumen posisional
  • **kwargs = kamus - kunci siapa yang menjadi argumen kata kunci terpisah dan nilainya menjadi nilai dari argumen ini.

Saya tidak mengerti tugas pemrograman apa yang akan membantu untuk ini.

Mungkin:

Saya pikir untuk memasukkan daftar dan kamus sebagai argumen dari suatu fungsi DAN pada saat yang sama sebagai wildcard, jadi saya bisa melewati argumen APAPUN?

Apakah ada contoh sederhana untuk menjelaskan caranya *args dan **kwargs digunakan?

Juga tutorial yang saya temukan hanya menggunakan "*" dan nama variabel.

Adalah *args dan **kwargs hanya placeholder atau yang Anda gunakan persis *args dan **kwargs dalam kode?


1189
2017-08-03 08:28


asal


Jawaban:


Sintaksnya adalah * dan **. Nama *args dan **kwargs hanya dengan konvensi tetapi tidak ada persyaratan yang sulit untuk menggunakannya.

Anda akan menggunakan *args ketika Anda tidak yakin berapa banyak argumen yang mungkin dilewatkan ke fungsi Anda, yaitu memungkinkan Anda mengirimkan sejumlah argumen acak ke fungsi Anda. Sebagai contoh:

>>> def print_everything(*args):
        for count, thing in enumerate(args):
...         print( '{0}. {1}'.format(count, thing))
...
>>> print_everything('apple', 'banana', 'cabbage')
0. apple
1. banana
2. cabbage

Demikian pula, **kwargs memungkinkan Anda menangani argumen bernama yang belum Anda definisikan sebelumnya:

>>> def table_things(**kwargs):
...     for name, value in kwargs.items():
...         print( '{0} = {1}'.format(name, value))
...
>>> table_things(apple = 'fruit', cabbage = 'vegetable')
cabbage = vegetable
apple = fruit

Anda dapat menggunakan ini bersama dengan argumen yang disebutkan juga. Argumen eksplisit mendapatkan nilai pertama dan kemudian segala sesuatu dilewatkan *args dan **kwargs. Argumen bernama muncul pertama dalam daftar. Sebagai contoh:

def table_things(titlestring, **kwargs)

Anda juga dapat menggunakan keduanya dalam definisi fungsi yang sama tetapi *args harus terjadi sebelumnya **kwargs.

Anda juga bisa menggunakan * dan ** sintaks saat memanggil suatu fungsi. Sebagai contoh:

>>> def print_three_things(a, b, c):
...     print( 'a = {0}, b = {1}, c = {2}'.format(a,b,c))
...
>>> mylist = ['aardvark', 'baboon', 'cat']
>>> print_three_things(*mylist)
a = aardvark, b = baboon, c = cat

Seperti yang Anda lihat dalam kasus ini, daftar (atau tupel) yang diperlukan mengambil dan memaketkannya. Dengan ini, mereka cocok dengan argumen dalam fungsi. Tentu saja, Anda bisa memiliki * baik dalam definisi fungsi dan dalam panggilan fungsi.


1472
2017-08-03 08:38



Satu tempat di mana penggunaan *args dan **kwargs cukup berguna untuk subclassing.

class Foo(object):
    def __init__(self, value1, value2):
        # do something with the values
        print value1, value2

class MyFoo(Foo):
    def __init__(self, *args, **kwargs):
        # do something else, don't care about the args
        print 'myfoo'
        super(MyFoo, self).__init__(*args, **kwargs)

Dengan cara ini Anda dapat memperluas perilaku kelas Foo, tanpa harus mengetahui terlalu banyak tentang Foo. Ini bisa sangat mudah jika Anda memprogram ke API yang mungkin berubah. MyFoo hanya meneruskan semua argumen ke kelas Foo.


442
2017-08-03 08:39



Berikut ini contoh yang menggunakan 3 jenis parameter berbeda.

def func(required_arg, *args, **kwargs):
    # required_arg is a positional-only parameter.
    print required_arg

    # args is a tuple of positional arguments,
    # because the parameter name has * prepended.
    if args: # If args is not empty.
        print args

    # kwargs is a dictionary of keyword arguments,
    # because the parameter name has ** prepended.
    if kwargs: # If kwargs is not empty.
        print kwargs

>>> func()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: func() takes at least 1 argument (0 given)

>>> func("required argument")
required argument

>>> func("required argument", 1, 2, '3')
required argument
(1, 2, '3')

>>> func("required argument", 1, 2, '3', keyword1=4, keyword2="foo")
required argument
(1, 2, '3')
{'keyword2': 'foo', 'keyword1': 4}

278
2017-08-03 08:42



Inilah salah satu tempat favorit saya untuk menggunakan ** sintaks seperti pada contoh terakhir Dave Webb:

mynum = 1000
mystr = 'Hello World!'
print "{mystr} New-style formatting is {mynum}x more fun!".format(**locals())

Saya tidak yakin apakah itu sangat cepat jika dibandingkan dengan hanya menggunakan nama itu sendiri, tetapi jauh lebih mudah untuk mengetik!


65
2017-08-03 13:03



Satu kasus di mana * args dan ** kwargs berguna adalah ketika menulis fungsi wrapper (seperti dekorator) yang harus dapat menerima argumen acak untuk melewati ke fungsi yang dibungkus. Misalnya, dekorator sederhana yang mencetak argumen dan mengembalikan nilai dari fungsi yang sedang dibungkus:

def mydecorator( f ):
   @functools.wraps( f )
   def wrapper( *args, **kwargs ):
      print "Calling f", args, kwargs
      v = f( *args, **kwargs )
      print "f returned", v
      return v
   return wrapper

39
2017-08-03 08:40



* args dan ** kwargs adalah fitur khusus-magic dari Python. Pikirkan fungsi yang bisa memiliki jumlah argumen yang tidak diketahui. Misalnya, untuk alasan apa pun, Anda ingin memiliki fungsi yang menjumlahkan nomor tak dikenal (dan Anda tidak ingin menggunakan fungsi penjumlahan built-in). Jadi Anda menulis fungsi ini:

def sumFunction(*args):
  result = 0
  for x in args:
    result += x
  return result

dan gunakan seperti: sumFunction (3,4,6,3,6,8,9).

** kwargs memiliki fungsi yang berbeda. Dengan ** kwargs, Anda dapat memberikan argumen kata kunci acak ke suatu fungsi dan Anda dapat mengaksesnya sebagai diktasi.

def someFunction(**kwargs):
  if 'text' in kwargs:
    print kwargs['text']

Memanggil beberapa Fungsi (text = "foo") akan mencetak foo.


35
2017-08-03 08:40



Bayangkan saja Anda memiliki fungsi tetapi Anda tidak ingin membatasi jumlah parameter yang diperlukan. Contoh:

>>> import operator
>>> def multiply(*args):
...  return reduce(operator.mul, args)

Kemudian Anda menggunakan fungsi ini seperti:

>>> multiply(1,2,3)
6

or

>>> numbers = [1,2,3]
>>> multiply(*numbers)
6

17
2017-08-03 08:40



Nama *args dan **kwargs atau **kw murni berdasarkan konvensi. Ini mempermudah kita untuk membaca kode masing-masing

Satu tempat itu berguna adalah ketika menggunakan modul struct

struct.unpack() mengembalikan tuple sedangkan struct.pack() menggunakan sejumlah argumen variabel. Saat memanipulasi data, akan lebih mudah untuk melewatkan tuple ke struck.pack() misalnya.

tuple_of_data = struct.unpack(format_str, data)
... manipulate the data
new_data = struct.pack(format_str, *tuple_of_data)

tanpa kemampuan ini Anda akan dipaksa untuk menulis

new_data = struct.pack(format_str, tuple_of_data[0], tuple_of_data[1], tuple_of_data[2],...)

yang juga berarti jika format_str berubah dan ukuran tupel berubah, saya harus kembali dan mengedit baris yang sangat panjang


14
2017-08-03 08:32



Perhatikan bahwa * args / ** kwargs adalah bagian dari sintaks fungsi-panggilan, dan bukan benar-benar operator. Ini memiliki efek samping tertentu yang saya hadapi, yaitu bahwa Anda tidak dapat menggunakan * args ekspansi dengan pernyataan cetak, karena cetak bukan fungsi.

Ini tampaknya masuk akal:

def myprint(*args):
    print *args

Sayangnya tidak mengkompilasi (kesalahan sintaks).

Ini mengkompilasi:

def myprint(*args):
    print args

Tapi cetak argumen sebagai tupel, yang bukan yang kita inginkan.

Ini adalah solusi yang saya selesaikan:

def myprint(*args):
    for arg in args:
        print arg,
    print

9
2017-11-10 21:07



Parameter ini biasanya digunakan untuk fungsi proxy, sehingga proxy dapat meneruskan parameter masukan apa pun ke fungsi target.

def foo(bar=2, baz=5):
    print bar, baz

def proxy(x, *args, **kwargs): # reqire parameter x and accept any number of additional arguments
    print x
    foo(*args, **kwargs) # applies the "non-x" parameter to foo

proxy(23, 5, baz='foo') # calls foo with bar=5 and baz=foo
proxy(6)# calls foo with its default arguments
proxy(7, bar='asdas') # calls foo with bar='asdas' and leave baz default argument

Tapi karena parameter ini menyembunyikan nama parameter yang sebenarnya, lebih baik menghindarinya.


7
2017-08-03 08:41