Jadi saya mengalami kesulitan dengan konsep *args
dan **kwargs
.
Sejauh ini saya telah belajar bahwa:
*args
= daftar argumen - sebagai argumen posisional**kwargs
= kamus - yang kuncinya menjadi argumen kata kunci terpisah dan nilai menjadi nilai argumen ini.
Saya tidak mengerti tugas pemrograman apa yang akan membantu ini.
Mungkin:
Saya pikir untuk memasukkan daftar dan kamus sebagai argumen fungsi DAN pada saat yang sama sebagai wildcard, sehingga saya bisa memberikan argumen APA SAJA?
Apakah ada contoh sederhana untuk menjelaskan bagaimana *args
dan **kwargs
digunakan?
Juga tutorial yang saya temukan hanya menggunakan "*" dan nama variabel.
Apakah *args
dan **kwargs
hanya placeholder atau Anda menggunakan *args
dan **kwargs
persis dalam kode?
Sintaksnya adalah *
dan **
. Nama-nama *args
dan **kwargs
hanya berdasarkan konvensi tetapi tidak ada persyaratan sulit untuk menggunakannya.
Anda akan menggunakan *args
ketika Anda tidak yakin berapa banyak argumen yang dapat diteruskan ke fungsi Anda, yaitu itu memungkinkan Anda meneruskan sejumlah argumen sewenang-wenang
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 untuk 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 bernama juga. Argumen eksplisit mendapatkan nilai pertama dan kemudian semua yang lain diteruskan ke *args
dan **kwargs
. Argumen bernama datang pertama dalam daftar. Sebagai contoh:
def table_things[titlestring, **kwargs]
Anda juga dapat menggunakan keduanya dalam definisi fungsi yang sama tetapi
*args
harus terjadi sebelum **kwargs
.
Anda juga dapat menggunakan sintaks *
dan **
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 dapat Anda lihat dalam kasus ini dibutuhkan daftar [atau Tuple] item dan membongkar item. Dengan ini itu cocok dengan argumen dalam fungsi. Tentu saja, Anda dapat memiliki *
baik dalam definisi fungsi dan dalam pemanggilan fungsi.
Satu tempat di mana penggunaan *args
dan **kwargs
cukup berguna adalah untuk subkelas.
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 tahu terlalu banyak tentang Foo. Ini bisa sangat nyaman jika Anda memprogram ke API yang mungkin berubah. MyFoo hanya meneruskan semua argumen ke kelas Foo.
Berikut ini contoh yang menggunakan 3 jenis parameter yang 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 "", line 1, in
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}
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 ini sangat cepat jika dibandingkan dengan hanya menggunakan nama sendiri, tetapi jauh lebih mudah untuk mengetik!
Satu kasus di mana * args dan ** kwargs berguna adalah ketika menulis fungsi wrapper [seperti dekorator] yang perlu dapat menerima argumen sewenang-wenang untuk melewati fungsi yang sedang dibungkus. Misalnya, dekorator sederhana yang mencetak argumen dan mengembalikan nilai 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
* args dan ** kwargs adalah fitur sihir khusus Python. Pikirkan fungsi yang bisa memiliki jumlah argumen yang tidak diketahui. Misalnya, untuk alasan apa pun, Anda ingin memiliki fungsi yang menjumlahkan jumlah angka yang tidak diketahui [dan Anda tidak ingin menggunakan fungsi jumlah bawaan] 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 sewenang-wenang ke suatu fungsi dan Anda dapat mengaksesnya sebagai kamus.
def someFunction[**kwargs]:
if 'text' in kwargs:
print kwargs['text']
Memanggil someFunction [text = "foo"] akan mencetak foo.
Bayangkan saja Anda memiliki fungsi tetapi Anda tidak ingin membatasi jumlah parameter yang dibutuhkan. Contoh:
>>> import operator
>>> def multiply[*args]:
... return reduce[operator.mul, args]
Maka Anda menggunakan fungsi ini seperti:
>>> multiply[1,2,3]
6
or
>>> numbers = [1,2,3]
>>> multiply[*numbers]
6
Nama-nama *args
dan **kwargs
atau **kw
murni berdasarkan konvensi. Itu memudahkan kita untuk membaca kode masing-masing
Satu tempat yang mudah digunakan adalah ketika menggunakan modul struct
struct.unpack[]
mengembalikan Tuple sedangkan struct.pack[]
menggunakan sejumlah variabel
argumen. Saat memanipulasi data, lebih mudah untuk mengirimkan 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 perubahan format_str dan ukuran perubahan Tuple, saya harus kembali dan mengedit garis yang sangat panjang
Perhatikan bahwa * args/** kwargs adalah bagian dari sintaks pemanggilan fungsi, dan bukan benar-benar operator. Ini memiliki efek samping tertentu yang saya alami, yaitu Anda tidak dapat menggunakan ekspansi * args dengan pernyataan cetak, karena cetak bukan fungsi.
Ini masuk akal:
def myprint[*args]:
print *args
Sayangnya itu tidak dikompilasi [kesalahan sintaks].
Ini mengkompilasi:
def myprint[*args]:
print args
Tetapi mencetak argumen sebagai Tuple, yang bukan itu yang kita inginkan.
Ini adalah solusi yang saya pilih:
def myprint[*args]:
for arg in args:
print arg,
print
Parameter ini biasanya digunakan untuk fungsi proxy, sehingga proxy dapat meneruskan parameter input 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
Tetapi karena parameter ini menyembunyikan nama parameter yang sebenarnya, lebih baik untuk menghindarinya.
Anda dapat melihat python docs [docs.python.org di FAQ], tetapi lebih khusus untuk penjelasan yang baik miss miss yang misterius dan tuan kwargs [milik arsip.org] [aslinya, tautan mati adalah sini ].
Singkatnya, keduanya digunakan ketika parameter opsional untuk suatu fungsi atau metode digunakan. Seperti yang dikatakan Dave, * args digunakan ketika Anda tidak tahu berapa banyak argumen yang dapat diloloskan, dan ** kwargs ketika Anda ingin menangani parameter yang ditentukan oleh nama dan nilai seperti pada:
myfunction[myarg=1]