เครื่องหมายดอกจันในการเรียกใช้ฟังก์ชัน


112

ฉันใช้ itertools.chain เพื่อ "แบน" รายการในลักษณะนี้:

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

สิ่งนี้แตกต่างจากการพูดอย่างไร:

uniqueCrossTabs = list(itertools.chain(uniqueCrossTabs))

8
ดูที่การคลายการบรรจุรายการอาร์กิวเมนต์ในเอกสาร Python สำหรับข้อมูลเพิ่มเติม
ไก่

8
คุณควรตรวจสอบ**โอเปอเรเตอร์ - มันทำเช่นเดียวกับ*แต่มีอาร์กิวเมนต์คำหลัก
Sean Vieira

คำตอบ:


182

* คือโอเปอเรเตอร์ "splat": ใช้รายการเป็นอินพุตและขยายเป็นอาร์กิวเมนต์ตำแหน่งจริงในการเรียกใช้ฟังก์ชัน

ถ้าuniqueCrossTabsเป็น[ [ 1, 2 ], [ 3, 4 ] ]เช่นนั้นitertools.chain(*uniqueCrossTabs)ก็เหมือนกับที่พูดitertools.chain([ 1, 2 ], [ 3, 4 ])

uniqueCrossTabsนี้จะเห็นได้ชัดที่แตกต่างจากที่ผ่านในเวลาเพียง ในกรณีของคุณคุณมีรายการที่คุณต้องการจะแบน อะไรitertools.chain()ส่งคืนตัววนซ้ำในการต่อกันของอาร์กิวเมนต์ตำแหน่งทั้งหมดที่คุณส่งผ่านไปยังอาร์กิวเมนต์ตำแหน่งแต่ละอาร์กิวเมนต์สามารถทำซ้ำได้ในสิทธิของตัวเอง

กล่าวอีกนัยหนึ่งคือคุณต้องการส่งผ่านแต่ละรายการuniqueCrossTabsเป็นอาร์กิวเมนต์chain()ซึ่งจะรวมเข้าด้วยกัน แต่คุณไม่มีรายการในตัวแปรแยกต่างหากดังนั้นคุณจึงใช้*โอเปอเรเตอร์เพื่อขยายรายการของรายการเป็นอาร์กิวเมนต์หลายรายการ

ดังที่ Jochen Ritzel ได้ชี้ให้เห็นในความคิดเห็นchain.from_iterable()นั้นเหมาะสมกว่าสำหรับการดำเนินการนี้เนื่องจากถือว่าการทำซ้ำเพียงครั้งเดียวเริ่มต้นด้วย จากนั้นรหัสของคุณจะกลายเป็น:

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

9
@larsmans: ฉันคิดว่าคำนี้เป็นที่นิยมมากขึ้นในโลกของ Ruby แต่ดูเหมือนว่าPythonจะยอมรับได้เช่นกันฉันชอบเพราะมันสนุกที่จะพูด ;-)
คาเมรอน

1
@larsmans: น่าสนใจ! ฉันคิดเสมอว่ามันอ้างถึงการกระทำของการคลายรายการลงในรายการอาร์กิวเมนต์ไม่ใช่ตัวละครจริง
Cameron

1
บางทีสตริงอาจไม่ใช่ตัวอย่างที่ดีที่สุดเพราะไม่ใช่ทุกคนที่เห็นสตริงเป็นซ้ำ Btw: แทนที่จะฉันเขียนchain(*it) chain.from_iterable(it)
Jochen Ritzel

@Jochen: คุณพูดถูกจริงๆฉันจะเปลี่ยนเป็นใช้ตัวเลขแทน นอกจากนี้ฉันไม่รู้ด้วยซ้ำว่าfrom_iterableมีอยู่จริง! ฉันจะเพิ่มในคำตอบของฉันในไม่ช้า
Cameron

1
@Ramy: *ใช้สำหรับการระเบิดรายการเป็นอาร์กิวเมนต์ตำแหน่งของฟังก์ชันเท่านั้น (ใช่เฉพาะเจาะจงมาก) คุณสามารถทำfor l in uniqueCrossTabs:ซ้ำได้ น่าเสียดายที่มันยากที่จะเห็น*ในที่ทำงานเนื่องจากใช้งานได้เฉพาะเมื่อคุณส่งรายการไปยังฟังก์ชัน (แทนที่จะส่งรายการเป็นพารามิเตอร์แรก*ทำให้แต่ละองค์ประกอบในรายการถูกส่งผ่านเป็นพารามิเตอร์แยกกันทีละรายการ ราวกับว่ามีการพิมพ์โดยคั่นด้วยเครื่องหมายจุลภาคในรายการพารามิเตอร์)
คาเมรอน

72

แบ่งลำดับออกเป็นอาร์กิวเมนต์แยกต่างหากสำหรับการเรียกใช้ฟังก์ชัน

>>> 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

เป็นเพียงทางเลือกในการอธิบายแนวคิด / การใช้งาน

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
นี่เป็นสิ่งสำคัญและไม่ได้กล่าวถึงในที่อื่น
Gershom

1
คำตอบนี้ใช้ไม่ได้กับคำถามโดยเฉพาะ แต่เป็นการประยุกต์ใช้เครื่องหมายดอกจันที่สำคัญ (ฉันคิดว่าเหมาะสมภายใต้ชื่อ "หมอก") นอกจากนี้ยังมีแอปพลิเคชั่นที่สำคัญอีกตัวหนึ่งอยู่ในข้อกำหนดฟังก์ชันdef func(a, b, *args):ดูคำตอบนี้สำหรับข้อมูลเพิ่มเติม
ASL
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.