Bir işleve değişken sayıda bağımsız değişken iletilebilir mi?


345

Varargs'ı C veya C ++ ile kullanmaya benzer şekilde:

fn(a, b)
fn(a, b, c, d, ...)

5
Onurlu lottness'i podcast 53'e yönlendiriyorum: itc.conversationsnetwork.org/shows/…
David Sykes

2
Bu konuda Bay Lott ile gitmeliyim. Bu konuda Python belgelerinde hızlı bir şekilde yetkili bir cevap alabilirsiniz, ayrıca belgelerde başka neler olduğu hakkında bir fikir edineceksiniz. Python'da çalışmayı planlıyorsanız, bu dokümanları tanımak sizin yararınıza olacaktır.
Brian Neal,

@DavidSykes Bağlantı koptu
Dave Liu

Yanıtlar:


447

Evet. Anahtar kelime olmayan*args bir bağımsız değişken olarak kullanabilirsiniz . Böylece istediğiniz sayıda argümanı iletebilirsiniz.

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)

Gördüğünüz gibi, Python olacak paketten bütün argümanları ile tek başlığın olarak argümanlar.

Anahtar kelime bağımsız değişkenleri için, bunları Skurmedel'in yanıtında gösterildiği gibi ayrı bir gerçek bağımsız değişken olarak kabul etmeniz gerekir .


8
Ayrıca önemli ... bilinmeyen sayıda argümanı bir işleve geçirmek zorunda kaldıklarında zaman bulunabilir. "Args" isimli bir liste oluşturup geçirerek bu çağrı senin "manyArgs" gibi bir durumda olduğunu böyle manyArgs "manyArgs (* args)" için
wilbbe01

4
Bu yakın, ama bu ne yazık ki yeterince genel değil: manyArgs(x = 3)başarısız TypeError. Skumedel'in cevabı bunun çözümünü göstermektedir. Anahtar nokta, bir fonksiyonun genel imzasının f(*list_args, **keyword_args)(değil f(*list_args)) olmasıdır.
Eric O Lebigot

2
Tipi argsDİR tuple. anahtar kelime değişkenlerikwargs anlamına gelir . Tipi DİR . kwargsdictionary
RoboAlex

1
Sadece for arg in args:geçirilen argümanlar üzerinden yineleme için
MasterControlProgram

228

Yayının çözülmesine ekleme:

Birden fazla anahtar / değer çifti de gönderebilirsiniz.

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

Ve ikisini karıştırabilirsiniz:

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

Hem bu sırayla bildirilmeli hem de çağrılmalıdır, yani işlev imzasının * argümanlar, ** kwargs olması ve bu sırayla çağrılması gerekir.


2
Myfunc'un (abc = 123, def = 456) nasıl çalıştığından emin değilim, ancak benimki (2.7) 'de, SyntaxError almadan bu işlevde' def 'iletilemiyor. Sanırım bunun nedeni def'nin python'da bir anlamı var. Bunun yerine myfunc'u (abc = 123, fgh = 567) deneyin. (Aksi takdirde, harika bir cevap ve bunun için teşekkürler!)
Dannid

@Dannid: Hiçbir fikrim yok haha ​​... 2.6 veya 3.2 üzerinde de çalışmaz. Yeniden adlandıracağım.
Skurmedel

'O sırayla çağrıldı' derken, o sırayla mı geçiyorsun? Veya başka bir şey?
Nikhil Prabhu

1
@NikhilPrabhu: Evet. Anahtar kelime bağımsız değişkenleri, aradığınızda son gelmelidir. Aramada da anahtar kelime olmayan bağımsız değişkenleriniz varsa her zaman sonuncu olurlar.
Skurmedel

2
Hemen değişimi: Python 3 için print abirlikte print(a)ve kwargs.iteritems():birlikte kwargs.items().
MasterControlProgram

22

Eğer yapabilirsem, Skurmedel'in kodu python 2 içindir; piton 3, değişime adapte etmek iteritemsiçin itemsve parantez eklemek print. Bu benim gibi yeni başlayanların içine girmesini önleyebilir: AttributeError: 'dict' object has no attribute 'iteritems've başka bir yerde arama yapabilir (ör. NetworkX'in write_shp () yöntemini kullanmaya çalışırken "'dict' nesnesinin` `iteritems '' özelliği yoktur ).

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

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

ve:

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

12

Diğer mükemmel gönderilere ekleme.

Bazen argümanlar sayısını belirtmek istemiyorum ve onlar için anahtarları (bir sözlükte geçen bir argüman yönteminde kullanılmazsa derleyici şikayet) kullanmak istiyorum.

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

Sonra böyle şeyler yapabilirsiniz

myfuns = [manyArgs1, manyArgs2]
for fun in myfuns:
  fun(args)

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'})
____________

yukarıdaki kod çıkacaktır

None None None
20 None 30
20 red 30

Bu, sözlük aracılığıyla değişken argümanları iletmek kadar iyidir


3
Bu korkunç bir kod. Çok daha iyi olurdu:f = lambda **dic: ' '.join(dic.get(key, 'None') for key in 'abc')
metaperture

0

Bu konuda ilerlemenin bir başka yolu, daha önce bahsedilen güzel cevapların yanı sıra, isteğe bağlı adlandırılmış argümanları konuma göre geçirebilmenize bağlıdır. Örneğin,

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

Verim

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

In [12]: f(1)
1
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.