İşlev çağrısında yıldız işareti


111

Listelerin bir listesini bu şekilde "düzleştirmek" için itertools.chain kullanıyorum:

uniqueCrossTabs = list(itertools.chain(*uniqueCrossTabs))

bu, şunu söylemekten nasıl farklıdır:

uniqueCrossTabs = list(itertools.chain(uniqueCrossTabs))

8
Daha fazla bilgi için Python belgelerinde argüman listelerini açma konusuna bakın .
Kai

8
**operatörü de kontrol etmelisiniz - *anahtar kelime argümanlarıyla aynı şeyi yapar .
Sean Vieira

Yanıtlar:


181

* "splat" operatörüdür: Bir listeyi girdi olarak alır ve onu işlev çağrısında gerçek konumsal argümanlara genişletir.

Yani eğer uniqueCrossTabsidi [ [ 1, 2 ], [ 3, 4 ] ], o zaman itertools.chain(*uniqueCrossTabs)diyerek aynıdıritertools.chain([ 1, 2 ], [ 3, 4 ])

Bu açıkça içeri girmekten farklı uniqueCrossTabs. Sizin durumunuzda, düzleştirmek istediğiniz listelerin bir listesi vardır; Ne itertools.chain()yapar her pozisyonel argüman kendi başına iterable olduğunu kendisine iletmek tüm pozisyonel argümanlar, birleşik bağ üzerinde bir yineleyici döndürür olduğunu.

Diğer bir deyişle, her listeyi uniqueCrossTabsbir argüman olarak iletmek istersiniz chain(), bu onları birbirine zincirler, ancak listeleri ayrı değişkenlere sahip değilsiniz, bu nedenle *listeleri birkaç liste argümanına genişletmek için operatörü kullanırsınız.

Jochen Ritzel'in yorumlarda belirttiği chain.from_iterable()gibi, başlamak için tek bir yinelenebilirliği varsaydığı için, bu işlem için daha uygundur. Kodunuz daha sonra basitleşir:

uniqueCrossTabs = list(itertools.chain.from_iterable(uniqueCrossTabs))

9
@larsmans: Sanırım bu terim Ruby dünyasında daha popüler, ancak Python için de kabul edilebilir görünüyor çünkü bunu söylemek eğlenceli ;-)
Cameron

1
@larsmans: İlginç! Her zaman listeyi bir argüman listesine açma eylemine atıfta bulunduğunu düşündüm, gerçek karakterin kendisine değil.
Cameron

1
Belki dizeler en iyi örnek değildir çünkü herkes dizeleri yinelenebilir olarak görmez. Btw: chain(*it)Yazmak yerine chain.from_iterable(it).
Jochen Ritzel

@Jochen: Kesinlikle haklısın, bunun yerine sayıları kullanacağım. Ayrıca, from_iterablevarlığından bile haberim yoktu ! Kısa süre
Cameron

1
@Ramy: *sadece listeyi konumsal argümanlara dönüştürerek bir fonksiyona dönüştürmek içindir (yani evet, çok spesifik). for l in uniqueCrossTabs:Onları yinelemek için yapabilirsiniz . Maalesef *işte bunu görmek zordur, çünkü yalnızca bir listeyi bir işleve geçirdiğinizde çalışır (listeyi ilk parametre olarak geçirmek yerine, listedeki *her öğenin birbiri ardına ayrı bir parametre olarak aktarılmasına neden olur. , sanki parametre listesinde virgülle ayrılmış şekilde yazılmış gibi)
Cameron

72

Sırayı, işlev çağrısı için ayrı bağımsız değişkenlere böler.

>>> def foo(a, b=None, c=None):
...   print a, b, c
... 
>>> foo([1, 2, 3])
[1, 2, 3] None None
>>> foo(*[1, 2, 3])
1 2 3
>>> def bar(*a):
...   print a
... 
>>> bar([1, 2, 3])
([1, 2, 3],)
>>> bar(*[1, 2, 3])
(1, 2, 3)

28

Sadece kavramı açıklamanın / kullanmanın alternatif bir yolu.

import random

def arbitrary():
    return [x for x in range(1, random.randint(3,10))]

a, b, *rest = arbitrary()

# a = 1
# b = 2
# rest = [3,4,5]

3
bu önemlidir ve başka yerde belirtilmemiştir
Gershom

1
Bu cevap özel olarak soru için geçerli değildir, ancak yıldız işaretinin önemli bir uygulamasıdır (bu yüzden "sisli" başlığı altında uygun olduğunu düşünüyorum). Aynı şekilde, bir başka önemli uygulama da işlev tanımları içindedir: def func(a, b, *args):Daha fazla bilgi için bu yanıta bakın .
ASL
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.