Pertanyaan Apakah mungkin untuk mengubah parameter default fungsi dengan Python?


Dengan Python, apakah mungkin untuk mendefinisikan kembali parameter default dari suatu fungsi pada saat runtime?

Saya mendefinisikan fungsi dengan 3 parameter di sini:

def multiplyNumbers(x,y,z):
    return x*y*z

print(multiplyNumbers(x=2,y=3,z=3))

Selanjutnya, saya mencoba (tidak berhasil) untuk menetapkan nilai parameter default untuk y, dan kemudian saya mencoba memanggil fungsi tanpa parameter y:

multiplyNumbers.y = 2;
print(multiplyNumbers(x=3, z=3))

Tetapi kesalahan berikut ini dihasilkan, karena nilai default dari y tidak disetel dengan benar:

TypeError: multiplyNumbers() missing 1 required positional argument: 'y'

Apakah mungkin untuk mendefinisikan kembali parameter default dari suatu fungsi pada saat runtime, seperti yang saya coba lakukan di sini?


8
2017-07-13 00:05


asal


Jawaban:


Cukup gunakan functools.partial

 multiplyNumbers = functools.partial(multiplyNumbers, y = 42)

Satu masalah di sini: Anda tidak akan bisa menyebutnya sebagai multiplyNumbers(5, 7, 9); Anda harus mengatakannya secara manual y=7

Jika Anda perlu menghapus argumen default, saya melihat dua cara:

  1. Simpan fungsi asli di suatu tempat

    oldF = f
    f = functools.partial(f, y = 42)
    //work with changed f
    f = oldF //restore
    
  2. menggunakan partial.func

    f = f.func //go to previous version.
    

23
2017-07-13 00:11



Secara teknis, adalah mungkin untuk melakukan apa yang Anda tanyakan ... tetapi itu bukan ide yang baik. Jawaban RiaD adalah cara Pythonic untuk melakukan ini.

Dengan Python 3:

>>> def f(x=1, y=2, z=3):
...     print(x, y, z)
>>> f()
1 2 3
>>> f.__defaults__ = (4, 5, 6)
4 5 6

Seperti semua yang ada di bawah selimut dan sulit ditemukan di dokumen, itu inspect bagan modul adalah tempat terbaik untuk mencari atribut fungsi.

Detailnya sedikit berbeda dengan Python 2, tetapi idenya sama. (Cukup ubah pulldown di kiri atas halaman dokumen dari 3.3 hingga 2.7.)


Jika Anda bertanya-tanya bagaimana Python mengetahui default yang pergi dengan argumen yang ketika itu hanya mendapat tuple ... itu hanya menghitung mundur dari akhir (atau yang pertama *, *args, **kwargs—Sesuatu setelah itu masuk ke dalam __kwdefaults__ pilih saja). f.__defaults = (4, 5) akan menetapkan default ke y dan z untuk 4 dan 5, dan dengan default untuk x. Itu berfungsi karena Anda tidak dapat memiliki parameter non-default setelah parameter default.


Ada beberapa kasus di mana ini tidak akan berfungsi, tetapi bahkan kemudian, Anda dapat menyalinnya ke fungsi baru dengan berbagai default:

>>> f2 = types.FunctionType(f.__code__, f.__globals__, f.__name__,
...                         (4, 5, 6), f.__closure__)

Di sini, the types modul dokumentasi tidak menjelaskan apa-apa, tapi help(types.FunctionType) di interpreter interaktif menunjukkan params yang Anda butuhkan.


Satu-satunya kasus Anda tidak bisa pegangan adalah fungsi bawaan. Tetapi mereka umumnya tidak memiliki default yang sebenarnya; sebaliknya, mereka memalsukan sesuatu yang serupa di API C.


7
2017-07-13 00:15



menggunakan func_defaults seperti dalam

def myfun(a=3):
    return a

myfun.func_defaults = (4,)
b = myfun()
assert b == 4

periksa dokumen untuk func_defaults sini

MEMPERBARUI: Melihat tanggapan RiaD, saya pikir saya terlalu harfiah dengan milik saya. Saya tidak tahu konteks dari mana Anda menanyakan pertanyaan ini tetapi secara umum (dan mengikuti Zen of Python) Saya percaya bekerja dengan aplikasi parsial adalah pilihan yang lebih baik daripada mendefinisikan ulang argumen default fungsi


0
2017-07-13 00:14