Baster tanda bintang dalam argumen fungsi?


242

Apa yang dilakukan tanda bintang kosong pada argumen fungsi?

Ketika saya melihat modul acar , saya melihat ini:

pickle.dump(obj, file, protocol=None, *, fix_imports=True)

Saya tahu tentang tanda bintang tunggal dan ganda sebelum argumen (untuk jumlah variabel argumen), tetapi ini tidak mendahului apa pun. Dan saya cukup yakin ini tidak ada hubungannya dengan acar. Itu mungkin hanya contoh dari kejadian ini. Saya baru tahu namanya ketika saya mengirim ini ke penerjemah:

>>> def func(*):
...     pass
...
  File "<stdin>", line 1
SyntaxError: named arguments must follow bare *

Jika itu penting, saya menggunakan python 3.3.0.


Jawaban:


221

Bare *digunakan untuk memaksa penelepon menggunakan argumen bernama - jadi Anda tidak dapat mendefinisikan fungsi dengan *sebagai argumen ketika Anda tidak memiliki argumen kata kunci berikut.

Lihat jawaban ini atau dokumentasi Python 3 untuk lebih jelasnya.


3
Perhatikan bahwa semua argumen posisi (tanpa nama), termasuk *args, harus muncul sebelum bare *.
BallpointBen

4
Perhatikan juga bahwa ada semacam rekanan, /, yang menandai akhir dari argumen hanya posisi ( stackoverflow.com/questions/28243832/… ).
Stephen

2
@BallpointBen: *ada di tempat *args, dan sebaliknya; mereka tidak bisa hidup berdampingan dalam tanda tangan. Itu sebabnya mereka memilih *; sebelumnya, *argsadalah satu-satunya cara untuk memaksakan argumen posisi murni, dan itu menandai akhir argumen yang dapat diajukan secara posisi (karena mengumpulkan semua argumen posisi yang tersisa, mereka dapat mencapai argumen bernama berikut). *berarti "argumen posisi yang sama tidak dapat melampaui sini", tetapi kurangnya nama berarti "tetapi saya tidak akan menerimanya sama sekali, karena saya memilih untuk tidak menyediakan tempat untuk meletakkannya".
ShadowRanger

70

Sementara jawaban asli menjawab pertanyaan sepenuhnya, hanya menambahkan sedikit informasi terkait. Perilaku untuk asterisk tunggal berasal dari PEP-3102. Mengutip bagian terkait:

The second syntactical change is to allow the argument name to
be omitted for a varargs argument. The meaning of this is to
allow for keyword-only arguments for functions that would not
otherwise take a varargs argument:

    def compare(a, b, *, key=None):
        ...

Dalam bahasa Inggris yang sederhana, ini berarti bahwa untuk meneruskan nilai kunci, Anda harus secara eksplisit meneruskannya sebagai key="value".


Oh, itu membuat segalanya lebih jelas. Jadi sebenarnya memiliki argumen * sama seperti memiliki argumen args *, tetapi karena Anda belum menyebutkannya, efeknya mungkin adalah dengan diam-diam melahap semua argumen posisi yang tersisa, untuk memaksa argumen yang tersisa menjadi kata kunci. -hanya.
Stephen

11
@Stephen Saya awalnya berpikir, efek bare *adalah melahap argumen posisi yang tersisa, tapi bukan itu masalahnya. Melewati argumen posisi ekstra dari fungsi yang diharapkan, memberikan kesalahan seperti ini:foo() takes exactly 1 positional argument (2 given)
Ajay M

19
def func(*, a, b):
    print(a)
    print(b)

func("gg") # TypeError: func() takes 0 positional arguments but 1 was given
func(a="gg") # TypeError: func() missing 1 required keyword-only argument: 'b'
func(a="aa", b="bb", c="cc") # TypeError: func() got an unexpected keyword argument 'c'
func(a="aa", b="bb", "cc") # SyntaxError: positional argument follows keyword argument
func(a="aa", b="bb") # aa, bb

contoh di atas dengan ** kwargs

def func(*, a, b, **kwargs):
    print(a)
    print(b)
    print(kwargs)

func(a="aa",b="bb", c="cc") # aa, bb, {'c': 'cc'}

6

Secara semantik, itu berarti argumen yang mengikutinya hanya kata kunci, jadi Anda akan mendapatkan kesalahan jika Anda mencoba memberikan argumen tanpa menyebutkan namanya. Sebagai contoh:

>>> def f(a, *, b):
...     return a + b
...
>>> f(1, 2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() takes 1 positional argument but 2 were given
>>> f(1, b=2)
3

Secara pragmatis, itu berarti Anda harus memanggil fungsi dengan argumen kata kunci. Ini biasanya dilakukan ketika akan sulit untuk memahami tujuan argumen tanpa petunjuk yang diberikan oleh nama argumen.

Bandingkan misalnya sorted(nums, reverse=True)vs. jika Anda menulis sorted(nums, True). Yang terakhir akan jauh lebih mudah dibaca, sehingga pengembang Python memilih untuk membuat Anda menulis dengan cara sebelumnya.


4

Misalkan Anda memiliki fungsi:

def sum(a,key=5):
    return a + key 

Anda dapat memanggil fungsi ini dalam 2 cara:

sum(1,2) atau sum(1,key=2)

Misalkan Anda ingin berfungsi sum dipanggil hanya menggunakan argumen kata kunci.

Anda menambahkan * ke daftar parameter fungsi untuk menandai akhir argumen posisi.

Jadi fungsinya didefinisikan sebagai:

def sum(a,*,key=5):
    return a + key 

dapat disebut hanya menggunakan sum(1,key=2)


-1

Saya menemukan tautan berikut ini sangat membantu menjelaskan *, *argsdan **kwargs:

https://pythontips.com/2013/08/04/args-and-kwargs-in-python-explained/

Intinya, selain jawaban di atas, saya sudah belajar dari situs di atas (kredit: https://pythontips.com/author/yasoob008/ ) berikut ini:

Dengan fungsi demonstrasi didefinisikan pertama di bawah ini, ada dua contoh, satu dengan *argsdan satu dengan**kwargs

def test_args_kwargs(arg1, arg2, arg3):
    print "arg1:", arg1
    print "arg2:", arg2
    print "arg3:", arg3

# first with *args
>>> args = ("two", 3,5)
>>> test_args_kwargs(*args)
arg1: two
arg2: 3
arg3: 5

# now with **kwargs:
>>> kwargs = {"arg3": 3, "arg2": "two","arg1":5}
>>> test_args_kwargs(**kwargs)
arg1: 5
arg2: two
arg3: 3

Jadi *argsmemungkinkan Anda untuk secara dinamis membangun daftar argumen yang akan diambil sesuai urutan pemberiannya**kwargs dapat memungkinkan berlalunya argumen NAMED, dan dapat diproses oleh NAME sesuai (terlepas dari urutan pemberiannya) .

Situs berlanjut, mencatat bahwa urutan argumen yang benar adalah:

some_func(fargs,*args,**kwargs)

2
Jawaban ini hampir tidak ada hubungannya dengan pertanyaan. Ia bahkan menggunakan versi python usang yang tidak memiliki fitur.
Antti Haapala
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.