Bisakah sejumlah variabel argumen diteruskan ke suatu fungsi?

345

Dengan cara yang mirip dengan menggunakan varargs di C atau C ++:

fn(a, b)
fn(a, b, c, d, ...)
David Sykes
sumber
5
Saya merujuk lottness terhormat ke podcast 53: itc.conversationsnetwork.org/shows/…
David Sykes
2
Aku harus pergi dengan Tuan Lott untuk yang ini. Anda dapat dengan cepat mendapatkan jawaban otoritatif yang satu ini di Python docs, plus Anda akan merasakan apa lagi yang ada di docs. Adalah bermanfaat bagi Anda untuk mengenal dokumen-dokumen itu jika Anda berencana untuk bekerja dengan Python.
Brian Neal
@DavidSykes Link rusak
Dave Liu

Jawaban:

447

Iya. Anda dapat menggunakan *argssebagai argumen non-kata kunci . Anda kemudian dapat melewati sejumlah argumen.

def manyArgs(*arg):
  print "I was called with", len(arg), "arguments:", arg

>>> manyArgs(1)
I was called with 1 arguments: (1,)
>>> manyArgs(1, 2, 3)
I was called with 3 arguments: (1, 2, 3)

Seperti yang Anda lihat, Python akan membongkar argumen sebagai satu tupel dengan semua argumen.

Untuk argumen kata kunci, Anda harus menerimanya sebagai argumen aktual yang terpisah, seperti yang ditunjukkan dalam jawaban Skurmedel .

beristirahat
sumber
8
Juga penting ... seseorang mungkin menemukan waktu ketika mereka harus memberikan sejumlah argumen ke suatu fungsi. Dalam kasus seperti ini panggil "manyArgs" Anda dengan membuat daftar yang disebut "args" dan meneruskannya ke manyArgs seperti ini "manyArgs (* args)"
wilbbe01
4
Ini dekat, tetapi sayangnya ini tidak cukup umum: manyArgs(x = 3)gagal dengan TypeError. Jawaban Skumedel menunjukkan solusi untuk ini. Poin kuncinya adalah bahwa tanda tangan umum suatu fungsi adalah f(*list_args, **keyword_args)(bukan f(*list_args)).
Eric O Lebigot
2
Jenisnya argsadalah tuple. kwargsberarti args kata kunci . Jenisnya kwargsadalah dictionary.
RoboAlex
1
Hanya for arg in args:untuk mengulangi argumen yang sudah lewat
MasterControlProgram
228

Menambahkan ke unwinds postingan:

Anda juga dapat mengirim beberapa argumen nilai kunci.

def myfunc(**kwargs):
    # kwargs is a dictionary.
    for k,v in kwargs.iteritems():
         print "%s = %s" % (k, v)

myfunc(abc=123, efh=456)
# abc = 123
# efh = 456

Dan Anda dapat mencampur keduanya:

def myfunc2(*args, **kwargs):
   for a in args:
       print a
   for k,v in kwargs.iteritems():
       print "%s = %s" % (k, v)

myfunc2(1, 2, 3, banan=123)
# 1
# 2
# 3
# banan = 123

Keduanya harus dideklarasikan dan dipanggil dalam urutan itu, yaitu fungsi tanda tangan harus * args, ** kwargs, dan dipanggil dalam urutan itu.

Skurmedel
sumber
2
Tidak yakin bagaimana Anda membuat myfunc (abc = 123, def = 456) berfungsi, tetapi di milik saya (2.7), 'def' tidak dapat dilewati dalam fungsi ini tanpa mendapatkan SyntaxError. Saya berasumsi ini karena def memiliki arti dalam python. Coba myfunc (abc = 123, fgh = 567) sebagai gantinya. (Kalau tidak, jawaban yang bagus dan terima kasih untuk itu!)
Dannid
@Dannid: Tidak tahu juga haha ​​... tidak bekerja pada 2.6 atau 3.2. Saya akan mengganti nama itu.
Skurmedel
Ketika Anda mengatakan 'dipanggil dalam urutan itu', apakah maksud Anda lulus dalam urutan itu? Atau sesuatu yang lain?
Nikhil Prabhu
1
@NikhilPrabhu: Ya. Argumen kata kunci harus menjadi yang terakhir saat Anda menyebutnya. Mereka selalu datang terakhir jika Anda memiliki argumen non-kata kunci dalam panggilan juga.
Skurmedel
2
Untuk Python 3: Hanya tukar print adengan print(a), dan kwargs.iteritems():dengan kwargs.items().
MasterControlProgram
22

Kalau boleh, kode Skurmedel adalah untuk python 2; untuk beradaptasi untuk python 3, perubahan iteritemske itemsdan menambahkan kurung untuk print. Itu bisa mencegah pemula seperti saya untuk bertabrakan: AttributeError: 'dict' object has no attribute 'iteritems'dan mencari di tempat lain (misalnya objek "dict 'Kesalahan tidak memiliki atribut' iteritems '" ketika mencoba menggunakan write_shp () ) dari NetworkX mengapa hal ini terjadi.

def myfunc(**kwargs):
for k,v in kwargs.items():
   print("%s = %s" % (k, v))

myfunc(abc=123, efh=456)
# abc = 123
# efh = 456

dan:

def myfunc2(*args, **kwargs):
   for a in args:
       print(a)
   for k,v in kwargs.items():
       print("%s = %s" % (k, v))

myfunc2(1, 2, 3, banan=123)
# 1
# 2
# 3
# banan = 123
calocedrus
sumber
12

Menambahkan ke pos luar biasa lainnya.

Kadang-kadang Anda tidak ingin menentukan jumlah argumen dan ingin menggunakan kunci untuk mereka (kompiler akan mengeluh jika satu argumen yang dilewatkan dalam kamus tidak digunakan dalam metode ini).

def manyArgs1(args):
  print args.a, args.b #note args.c is not used here

def manyArgs2(args):
  print args.c #note args.b and .c are not used here

class Args: pass

args = Args()
args.a = 1
args.b = 2
args.c = 3

manyArgs1(args) #outputs 1 2
manyArgs2(args) #outputs 3

Maka Anda dapat melakukan hal-hal seperti

myfuns = [manyArgs1, manyArgs2]
for fun in myfuns:
  fun(args)
Vladtn
sumber
2
def f(dic):
    if 'a' in dic:
        print dic['a'],
        pass
    else: print 'None',

    if 'b' in dic:
        print dic['b'],
        pass
    else: print 'None',

    if 'c' in dic:
        print dic['c'],
        pass
    else: print 'None',
    print
    pass
f({})
f({'a':20,
   'c':30})
f({'a':20,
   'c':30,
   'b':'red'})
____________

kode di atas akan ditampilkan

None None None
20 None 30
20 red 30

Ini sama baiknya dengan melewatkan argumen variabel melalui kamus

BN Venkataraman
sumber
3
Ini kode yang mengerikan. Jauh lebih baik adalah:f = lambda **dic: ' '.join(dic.get(key, 'None') for key in 'abc')
metaperture
0

Cara lain untuk melakukannya, selain jawaban yang bagus yang telah disebutkan, tergantung pada fakta bahwa Anda dapat memberikan argumen opsional berdasarkan posisi. Sebagai contoh,

def f(x,y=None):
    print(x)
    if y is not None:
        print(y)

Hasil

In [11]: f(1,2)
1
2

In [12]: f(1)
1
kondisi transversalitas
sumber