Apakah ada cara untuk melewatkan parameter opsional ke suatu fungsi?

133

Apakah ada cara di Python untuk meneruskan parameter opsional ke fungsi saat memanggilnya dan dalam definisi fungsi memiliki beberapa kode berdasarkan "hanya jika parameter opsional dilewatkan"

pengguna1795998
sumber

Jawaban:

115

The Python 2 dokumentasi, 7,6. Definisi fungsi memberi Anda beberapa cara untuk mendeteksi apakah penelepon menyediakan parameter opsional.

Pertama, Anda dapat menggunakan sintaks parameter formal khusus *. Jika definisi fungsi memiliki parameter formal yang didahului oleh satu *, maka Python mengisi parameter itu dengan parameter posisi apa pun yang tidak cocok dengan parameter formal sebelumnya (sebagai tupel). Jika definisi fungsi memiliki parameter formal yang didahului oleh **, maka Python mengisi parameter itu dengan parameter kata kunci apa pun yang tidak cocok dengan parameter formal sebelumnya (sebagai dict). Implementasi fungsi dapat memeriksa konten dari parameter ini untuk "parameter opsional" apa pun yang Anda inginkan.

Misalnya, inilah fungsi opt_funyang mengambil dua parameter posisi x1dan x2, dan mencari parameter kata kunci lain bernama "opsional".

>>> def opt_fun(x1, x2, *positional_parameters, **keyword_parameters):
...     if ('optional' in keyword_parameters):
...         print 'optional parameter found, it is ', keyword_parameters['optional']
...     else:
...         print 'no optional parameter, sorry'
... 
>>> opt_fun(1, 2)
no optional parameter, sorry
>>> opt_fun(1,2, optional="yes")
optional parameter found, it is  yes
>>> opt_fun(1,2, another="yes")
no optional parameter, sorry

Kedua, Anda dapat memberikan nilai parameter default dari beberapa nilai Noneyang tidak akan pernah digunakan oleh penelepon. Jika parameter memiliki nilai default ini, Anda tahu penelepon tidak menentukan parameter. Jika parameter memiliki nilai non-default, Anda tahu itu berasal dari pemanggil.

Jim DeLaHunt
sumber
7
positional_parametersadalah tuple, dan keyword_parameterskamus.
Cees Timmerman
Bagaimana python membedakan formal parameters preceded by * (apa ini namanya?) Dari a keyword parameter? Seperti yang saya pahami, parameter kata kunci ditentukan menggunakan =operator dalam panggilan fungsi (jadi opt_fun(1,2, optional="yes")berikan argumen kata kunci "ya" untuk fungsi yang mengantisipasi, tetapi tidak selalu memerlukan, parameter option).
Minh Tran
Di sisi lain, saya mengerti formal parameters preceded by * hanya sebagai "argumen yang diberikan penelepon yang tidak sesuai dengan argumen posisional yang berjalan sebelum argumen kata kunci". Misalnya, di opt_fun(1,2, "blah", 3.14, mykey="yes", myyear="2018"), "blah"dan karena 3.14berada forma arguments preceded by *di antara dua argumen posisi dan argumen yang menggunakan =tanda. Tuple yang dihasilkan positional_parameterakan menjadi rangkap yang: ("blah", 3.14). Apakah ini benar?
Minh Tran
@ MinhTran, pertanyaan dalam komentar bukanlah cara terbaik untuk mendapatkan jawaban di Stack Overflow Jauh lebih baik mengklik tombol biru besar "Ajukan Pertanyaan", dan tulis permintaan Anda sebagai "Pertanyaan" yang dapat "Dijawab" oleh orang lain. Tetapi untuk membantu Anda, a) catatan saya menulis " parameter" bukan " parameters" untuk " preceded by *". Bahasa hanya memungkinkan satu *identifierdalam daftar parameter. b) baca docs.python.org/2/reference/… , c) baca docs.python.org/2/reference/expressions.html#calls . Maaf, kehabisan karakter yang diizinkan dalam komentar ini.
Jim DeLaHunt
81
def my_func(mandatory_arg, optional_arg=100):
    print(mandatory_arg, optional_arg)

http://docs.python.org/2/tutorial/controlflow.html#default-argument-values

Saya menemukan ini lebih mudah dibaca daripada menggunakan **kwargs.

Untuk menentukan apakah argumen telah dilewati sama sekali, saya menggunakan objek utilitas khusus sebagai nilai default:

MISSING = object()

def func(arg=MISSING):
    if arg is MISSING:
        ...
warvariuc
sumber
-Terima kasih, apakah ada cara untuk menentukan nilai default dari parameter ini sebagai variabel lain dalam kode?
user1795998
Iya. default_value=100; def my_func(mandatory_argument, optional_argument_with_default_value=default_value): ...
warvariuc
Tampaknya ini menunjukkan cara menggunakan parameter opsional, tetapi tidak bagaimana menguji jika ada yang dilewati, yang diminta OP.
Mawg mengatakan mengembalikan Monica
4
Dalam kebanyakan kasus, ini adalah solusi yang lebih sederhana dan lebih langsung daripada Jim. Jika Anda menetapkan nilai default ke Tidak ada maka Anda dapat memeriksa apakah parameternya telah berlalu atau tidak. Satu-satunya kasus di mana solusi Jim lebih baik adalah jika penting untuk membedakan antara melewati Tidak ada sebagai argumen dan tidak melewati argumen sama sekali.
Arnon Axelrod
19
def op(a=4,b=6):
    add = a+b
    print add

i)op() [o/p: will be (4+6)=10]
ii)op(99) [o/p: will be (99+6)=105]
iii)op(1,1) [o/p: will be (1+1)=2]
Note:
 If none or one parameter is passed the default passed parameter will be considered for the function. 
Sanyal
sumber
1
Apakah ada cara untuk lulus hanya parameter kedua (b) dan bukan yang pertama (a)?
Djidiouf
4
@ Djidiouf Ya, adaop(b=2)
Jürg Merlin Spaak
7

Jika Anda ingin memberikan beberapa nilai default ke nilai penetapan parameter di (). suka (x = 10). Tetapi yang penting adalah pertama-tama harus argumen wajib kemudian nilai default.

misalnya.

(y, x = 10)

tapi

(x = 10, y) salah

sumit
sumber
Terima kasih, apakah ada cara untuk menentukan nilai default dari parameter ini sebagai variabel lain dalam kode?
user1795998
Ya, Anda dapat menggunakan sesuatu yang disebut *arg **kargargumen fungsi. cari di google.
sumit
Tampaknya ini menunjukkan cara menggunakan parameter opsional, tetapi tidak bagaimana menguji jika ada yang dilewati, yang diminta OP.
Mawg mengatakan mengembalikan Monica
2

Anda dapat menentukan nilai default untuk argumen opsional dengan sesuatu yang tidak akan pernah diteruskan ke fungsi dan memeriksanya dengan isoperator:

class _NO_DEFAULT:
    def __repr__(self):return "<no default>"
_NO_DEFAULT = _NO_DEFAULT()

def func(optional= _NO_DEFAULT):
    if optional is _NO_DEFAULT:
        print("the optional argument was not passed")
    else:
        print("the optional argument was:",optional)

maka selama Anda tidak melakukannya, func(_NO_DEFAULT)Anda dapat secara akurat mendeteksi apakah argumennya disetujui atau tidak, dan tidak seperti jawaban yang diterima Anda tidak perlu khawatir tentang efek samping dari notasi **:

# these two work the same as using **
func()
func(optional=1)

# the optional argument can be positional or keyword unlike using **
func(1) 

#this correctly raises an error where as it would need to be explicitly checked when using **
func(invalid_arg=7)
Tadhg McDonald-Jensen
sumber
Lakukan saja _NO_DEFAULT = object().
Aran-Fey
2 baris ekstra untuk memberikan introspeksi yang lebih baik sangat berharga. Dengan ini jika Anda menjalankan help(func)Anda mendapatkan ide yang lebih jelas bagaimana argumen ditafsirkan jika tidak disahkan secara eksplisit.
Tadhg McDonald-Jensen