ตัว*
ดำเนินการหมายถึงอะไรใน Python เช่นในโค้ด like zip(*x)
หรือf(**k)
?
- วิธีการจัดการภายในล่าม?
- มีผลต่อประสิทธิภาพหรือไม่? เร็วหรือช้า?
- มีประโยชน์เมื่อใดและเมื่อใดไม่เป็นประโยชน์?
- ควรใช้ในการประกาศฟังก์ชันหรือในการโทร?
ตัว*
ดำเนินการหมายถึงอะไรใน Python เช่นในโค้ด like zip(*x)
หรือf(**k)
?
*
และ**
ผู้ประกอบการที่มีอะไรจะทำอย่างไรกับรูปแบบนี้
[*a, b, *c]
หรือ{**d1, **d2}
) คุณจะต้องอ่านเครื่องหมายดอกจันในทูเพิลแสดงรายการและกำหนดคำจำกัดความเครื่องหมายดอกจันคู่ในคำจำกัดความของคำสั่งซึ่งเฉพาะเจาะจงสำหรับการใช้งานนอกการเรียกฟังก์ชันและคำจำกัดความของฟังก์ชัน . สำหรับก่อนหน้านี้PEP 3132ดูการกำหนดเอาออกหลายในหลามเมื่อคุณไม่ทราบระยะเวลาในลำดับ
คำตอบ:
ดาวดวงเดียว*
คลายลำดับ / คอลเลกชันเป็นอาร์กิวเมนต์ตำแหน่งดังนั้นคุณสามารถทำได้:
def sum(a, b):
return a + b
values = (1, 2)
s = sum(*values)
สิ่งนี้จะคลาย tuple เพื่อให้ดำเนินการเป็น:
s = sum(1, 2)
ดาวคู่**
ทำเช่นเดียวกันโดยใช้พจนานุกรมเท่านั้นจึงตั้งชื่ออาร์กิวเมนต์:
values = { 'a': 1, 'b': 2 }
s = sum(**values)
คุณยังสามารถรวม:
def sum(a, b, c, d):
return a + b + c + d
values1 = (1, 2)
values2 = { 'c': 10, 'd': 15 }
s = sum(*values1, **values2)
จะดำเนินการเป็น:
s = sum(1, 2, c=10, d=15)
ดูส่วน4.7.4 - การคลายการบรรจุรายการอาร์กิวเมนต์ของเอกสาร Python
นอกจากนี้คุณสามารถกำหนดฟังก์ชันที่จะใช้*x
และ**y
อาร์กิวเมนต์ได้ซึ่งจะทำให้ฟังก์ชันยอมรับอาร์กิวเมนต์ตำแหน่งและ / หรือระบุชื่อจำนวนเท่าใดก็ได้ที่ไม่ได้ระบุชื่อเฉพาะในการประกาศ
ตัวอย่าง:
def sum(*values):
s = 0
for v in values:
s = s + v
return s
s = sum(1, 2, 3, 4, 5)
หรือด้วย**
:
def get_a(**values):
return values['a']
s = get_a(a=1, b=2) # returns 1
สิ่งนี้ช่วยให้คุณระบุพารามิเตอร์ทางเลือกจำนวนมากได้โดยไม่ต้องประกาศ
และอีกครั้งคุณสามารถรวม:
def sum(*values, **options):
s = 0
for i in values:
s = s + i
if "neg" in options:
if options["neg"]:
s = -s
return s
s = sum(1, 2, 3, 4, 5) # returns 15
s = sum(1, 2, 3, 4, 5, neg=True) # returns -15
s = sum(1, 2, 3, 4, 5, neg=False) # returns 15
s = sum((1, 2, 3, 4, 5))
หรือs = sum([1, 2, 3, 4, 5])
ที่*values
ตัวเลือกทำให้มองโทรเหมือนว่ามันจะใช้เวลาจำนวนของการขัดแย้ง แต่พวกเขากำลังบรรจุลงในคอลเลกชันสำหรับรหัสฟังก์ชั่น
จุดเล็ก ๆ อย่างหนึ่ง: สิ่งเหล่านี้ไม่ใช่ตัวดำเนินการ ตัวดำเนินการใช้ในนิพจน์เพื่อสร้างค่าใหม่จากค่าที่มีอยู่ (1 + 2 กลายเป็น 3 ตัวอย่างเช่น * และ ** ต่อไปนี้เป็นส่วนหนึ่งของไวยากรณ์ของการประกาศฟังก์ชันและการเรียกใช้
ฉันพบว่าสิ่งนี้มีประโยชน์อย่างยิ่งเมื่อคุณต้องการ "จัดเก็บ" การเรียกใช้ฟังก์ชัน
ตัวอย่างเช่นสมมติว่าฉันมีการทดสอบหน่วยสำหรับฟังก์ชัน 'add':
def add(a, b): return a + b
tests = { (1,4):5, (0, 0):0, (-1, 3):3 }
for test, result in tests.items():
print 'test: adding', test, '==', result, '---', add(*test) == result
ไม่มีวิธีอื่นใดในการเรียกเพิ่มนอกเหนือจากการทำสิ่งต่างๆด้วยตนเองเช่นเพิ่ม (ทดสอบ [0] ทดสอบ [1]) ซึ่งน่าเกลียด นอกจากนี้หากมีตัวแปรจำนวนตัวแปรโค้ดอาจดูน่าเกลียดพอสมควรกับ if-statement ทั้งหมดที่คุณต้องการ
สถานที่อื่นที่มีประโยชน์คือการกำหนดวัตถุจากโรงงาน (วัตถุที่สร้างวัตถุให้คุณ) สมมติว่าคุณมีคลาส Factory ที่สร้างวัตถุรถยนต์และส่งคืน คุณสามารถทำให้ myFactory.make_car ('red', 'bmw', '335ix') สร้าง Car ('red', 'bmw', '335ix') แล้วส่งกลับ
def make_car(*args):
return Car(*args)
นอกจากนี้ยังมีประโยชน์เมื่อคุณต้องการเรียกคอนสตรัคเตอร์ของ superclass
เรียกว่าไวยากรณ์การโทรแบบขยาย จากเอกสารประกอบ :
หากนิพจน์ไวยากรณ์ * ปรากฏในการเรียกใช้ฟังก์ชันนิพจน์ต้องประเมินเป็นลำดับ องค์ประกอบจากลำดับนี้จะถือว่าเป็นอาร์กิวเมนต์ตำแหน่งเพิ่มเติม หากมีอาร์กิวเมนต์ตำแหน่ง x1, ... , xN และนิพจน์ที่ประเมินเป็นลำดับ y1, ... , yM สิ่งนี้จะเทียบเท่ากับการเรียกที่มีอาร์กิวเมนต์ตำแหน่ง M + N x1, ... , xN, y1, .. , yM.
และ:
หากนิพจน์ไวยากรณ์ ** ปรากฏในการเรียกใช้ฟังก์ชันนิพจน์ต้องประเมินเป็นการแม็ปซึ่งเนื้อหาจะถือว่าเป็นอาร์กิวเมนต์คีย์เวิร์ดเพิ่มเติม ในกรณีของคีย์เวิร์ดปรากฏในทั้งนิพจน์และเป็นอาร์กิวเมนต์คีย์เวิร์ดที่ชัดเจนจะมีการเพิ่มข้อยกเว้น TypeError
apply()
ฟังก์ชันในตัว
ในการเรียกใช้ฟังก์ชันดาวดวงเดียวจะเปิดรายชื่อเข้าสู่การขัดแย้งแยก (เช่นzip(*x)
เป็นเช่นเดียวกับzip(x1,x2,x3)
ถ้าx=[x1,x2,x3]
) และดาวคู่จะเปิดพจนานุกรมเข้าไปในข้อโต้แย้งคำหลักที่แยกจากกัน (เช่นf(**k)
เป็นเช่นเดียวกับถ้าf(x=my_x, y=my_y)
k = {'x':my_x, 'y':my_y}
ในนิยามฟังก์ชันมันเป็นอีกทางหนึ่ง: ดาวดวงเดียวจะเปลี่ยนอาร์กิวเมนต์ตามจำนวนที่กำหนดให้เป็นรายการและการเริ่มต้นสองครั้งจะเปลี่ยนอาร์กิวเมนต์คำหลักตามจำนวนที่กำหนดลงในพจนานุกรม เช่นdef foo(*x)
หมายถึง "foo ใช้เวลาจำนวนข้อของการขัดแย้งและพวกเขาจะสามารถเข้าถึงได้ผ่านรายการ x (เช่นถ้าโทรของผู้ใช้foo(1,2,3)
, x
จะ[1,2,3]
)" และdef bar(**k)
หมายถึง "บาร์ใช้เวลาจำนวนข้อของข้อโต้แย้งคำหลักและพวกเขาจะสามารถเข้าถึงได้ผ่าน k พจนานุกรม (เช่นถ้าโทรของผู้ใช้bar(x=42, y=23)
, k
จะ{'x': 42, 'y': 23}
)"
def foo(*x)
* x ให้ทูเพิลไม่ใช่รายการ