รูปแบบที่จะใช้สำหรับพารามิเตอร์ส่งคืนที่ไม่ได้ใช้ในการเรียกใช้ฟังก์ชัน Python


30

มีรูปแบบการเข้ารหัสที่แนะนำ / ยอมรับโดยทั่วไปสำหรับการจัดการสถานการณ์ที่ฟังก์ชันส่งคืนค่า tuple แต่จะใช้ค่าเหล่านั้นเพียงหนึ่งค่าในภายหลัง (โปรดทราบว่านี่เป็นความหมายส่วนใหญ่สำหรับฟังก์ชั่นห้องสมุดที่ฉันไม่สามารถเปลี่ยนแปลงได้ การโทรน่าจะเกินกำลังเล็กน้อย ... )? แทนที่จะทำ

a, b, c = foo()

และจากนั้นก็ไม่ได้ใช้bและcควรเลือกอันใดของตัวแปรต่อไปนี้ (หรือมีอีกอันหนึ่ง):

ตัวแปร 1 (ขีดล่าง)

a, _, _ = foo()

(ซึ่งมีความชัดเจนและเรียบง่าย แต่อาจขัดแย้งกับการ_ = gettext.gettextใช้งานในหลาย ๆ แอปพลิเคชันที่ใช้การแปล)

ตัวแปร 2 (ชื่อจำลอง)

a, unused, unused = foo()

(ไม่น่าสนใจมากฉันคิดว่าเหมือนกันไปสำหรับชื่ออื่น ๆ เช่นdummy)

ตัวแปร 3 (ดัชนี)

a = foo()[0]

(สำหรับฉัน()[0]ภาพลักษณ์ที่ไม่ไพเราะ…)


มันตรงกันข้ามกับคำตอบเดิมของฉันเกิดอะไรขึ้นกับตัวแปร 3 เมื่อคุณต้องการอ้างอิง 2/3 ของค่าส่งคืน ฉันลบคำตอบของฉันออกเพราะฉันรู้ว่าฉันไม่รู้จัก Python มากพอที่จะพิสูจน์ว่าเหมาะสม
Craige

@Craige: ฉันไม่เห็นคำตอบของคุณก่อนที่คุณจะลบมัน ... คุณถามว่าa, b = foo()[0:2]จะใช้งานได้หรือไม่ ถ้าใช่: ใช่มันจะเป็นเช่นนั้น :)
user49643

นั่นคือสิ่งที่ฉันขอ หากใช้งานได้ (ตามที่คุณบอกว่าทำ) ฉันจะใช้ชุดตัวเลือก 3 ฉันจะใส่คำตอบของฉันอีกครั้งเมื่อได้รับข้อมูลนี้
Craige

3
บังเอิญวันนี้คุณสามารถใช้ไวยากรณ์ที่ค่อนข้างสวยงามสำหรับ'ขยาย' การเปิดออก : a, *_ = foo()จะทิ้งค่าทั้งหมดยกเว้นครั้งแรก
Benjamin Hodgson

คำตอบ:


17

การใช้ขีดล่างสำหรับตัวแปรที่ไม่ได้ใช้นั้นเป็นที่ยอมรับได้อย่างแน่นอน ถูกเตือนว่าใน codebases gettextบางอย่างมันไม่ได้เป็นตัวเลือกที่เป็นตัวระบุสงวนไว้เป็นชวเลข นี่คือการคัดค้านสไตล์นี้บ่อยที่สุด (แม้ว่าจะไม่ใช่ปัญหาสำหรับคนส่วนใหญ่เท่าที่ฉันสามารถตัดสินได้) ฉันยังคงแนะนำและใช้มันเองเสมอ

ชื่อชอบdummyหรือunusedมีแนวโน้มที่จะทำให้ฉันรำคาญใจเป็นการส่วนตัวและฉันไม่เห็นพวกเขาบ่อยนัก (ใน Python นั่นคือ - ฉันรู้จักเดลฟีโค้ดเบสซึ่งใช้dummyอย่างอิสระและมันก็รั่วเข้าไปในสคริปต์ที่เกี่ยวข้องกับโปรแกรมที่เป็นปัญหา) ฉันจะแนะนำคุณกับมัน

เพียงแค่ดึงหนึ่งไอเท็มจาก tuple ที่คืนมาก็โอเคเช่นกัน นอกจากนี้ยังช่วยลดความยุ่งยากบางอย่างด้วยการทำให้จำนวนค่าที่ไม่ได้ใช้ถูกต้อง โปรดทราบว่ามันมีข้อเสียที่อาจเกิดขึ้นสองประการ:

  • ไม่ระเบิดหากจำนวนค่าแตกต่างจากที่คุณคาดหวัง สิ่งนี้อาจมีประโยชน์ในการตรวจจับมิกซ์แอนด์ typos
  • ใช้งานได้เฉพาะเมื่อค่าส่งคืนเป็นลำดับ (ส่วนใหญ่จะเป็นอันดับและรายการ แต่ขอพูดโดยทั่วไป) โดยส่วนตัวแล้วฉันรู้หนึ่งคลาสในโค้ดของฉัน (เวกเตอร์ 2 มิติ) ที่สามารถทำซ้ำได้และให้ค่าจำนวนคงที่ (ซึ่งสามารถใช้ในการมอบหมายการเปิด) แต่ไม่สามารถทำดัชนีได้

จริง ๆ แล้วฉันได้พูดถึง gettext ในคำถามของฉัน :) อย่างไรก็ตามฉันยอมรับคำตอบของคุณ - ดูเหมือนว่าจะไม่มีสไตล์เดี่ยวที่ชัดเจน แต่คำตอบของคุณยกประเด็นที่น่าสนใจ
user49643

เพื่อหลีกเลี่ยงปัญหาเกี่ยวกับ gettext (หรือเพื่อหลีกเลี่ยงปัญหาที่คล้ายกันในล่าม) คุณสามารถใช้เครื่องหมายขีดล่างคู่ (aka dunders) แทนอันเดียว
ซิม

21

ไพลินทำให้ฉันมีนิสัยชอบทำสิ่งนี้:

widget, _parent, _children = f()

นั่นคือผลลัพธ์ที่ไม่ได้ใช้มีคำอธิบายชื่อนำหน้าด้วย _ ไพลินขอแสดงความนับถือชาวบ้านที่นำหน้าด้วย _ เป็นไม่ได้ใช้และกลมกลืนหรือแอตทริบิวต์นำหน้าด้วย _ เป็นส่วนตัว


3

หากในโครงการทั้งหมดของคุณคุณกำลังทำสิ่งนี้เพียงครั้งเดียวหรือน้อยมากฟังก์ชั่นพิเศษฉันจะใช้ Variant 1 ถ้าคุณรู้ว่าgettextไม่มีปัญหาในโมดูลนั้นและอย่างอื่น Variant 3

ในทางกลับกันถ้าคุณทำสิ่งนี้มาก - และโดยเฉพาะอย่างยิ่งถ้าแต่ละครั้งที่คุณต้องการเซตย่อยที่แตกต่างกันของค่าส่งคืน (การทำ wrapper ให้ส่งคืนสิ่งที่คุณสนใจเกี่ยวกับสิ่งที่ไม่น่าเชื่อถือ) มันอาจเป็นประโยชน์ในการเขียน wrapper ที่ทำให้ผลลัพธ์เป็นtuple ที่มีชื่อหรืออินสแตนซ์ของคลาสอธิบายอื่น ๆ ซึ่งจะช่วยให้คุณทำ:

bar = foo()

และจากนั้นก็ทำงานร่วมกับbar.a, และbar.bbar.c


2

ดังที่คนอื่น ๆ พูดขีดเส้นใต้ ( _) เป็นมาตรฐาน แต่ถ้าใช้ขีดเส้นใต้สำหรับการแปลฉันคิดว่าการขีดเส้นใต้คู่เป็นทางเลือกที่ดีที่สุด

var, __, value = "VAR=value".partition('=')

ดีกว่าสิ่งเหล่านี้:

var, unused, value = "VAR=value".partition('=')

var, unused_del, value = "VAR=value".partition('=')

var, _del, value = "VAR=value".partition('=')


1

ฉันไม่ใช่โปรแกรมเมอร์ของ Python แต่สำหรับฉันแล้วตัวแปรที่สามนั้นสมเหตุสมผลที่สุด

ในตัวแปรที่ 3 คุณมีความชัดเจนอย่างแน่นอนว่าคุณสนใจที่จะจัดการกับสิ่งใด ในชุดที่ 1 และ 2 คุณกำลังกำหนดค่ากลับไปที่ตัวแปรดังนั้นจึงสามารถใช้ได้ คุณอาจตั้งชื่อพวกเขาอย่างคลุมเครือ แต่การตั้งชื่อไม่ดีไม่ใช่ทางออกสำหรับปัญหาใด ๆ

นอกเหนือจากความชัดเจนแล้วเหตุใดคุณต้องการกำหนดค่าที่ไม่ได้ใช้ให้กับสล็อตในหน่วยความจำ (เช่นเดียวกับตัวแปร 1 และ 2) นี่จะเป็นทางออกที่ไม่ดีในแง่ของการจัดการหน่วยความจำ


หากคุณใส่ไว้ในตัวแปรเดียวกันเสมอจะไม่เกิดปัญหาหน่วยความจำเพียงขนาดของตัวแปรเดียวในเวลาที่กำหนดหรือไม่ ฉันไม่คิดว่าควรจะมีปัญหา
Michael McQuade

-2

นี่เป็นกฎทั่วไป: หากใช้เพียง 1 ในค่าที่ส่งคืนแล้วทำไมไม่คืนค่า 1 ค่านั้น ในกรณีที่มีการเรียกใช้แฟล็กจากหลาย ๆ ที่ให้เก็บค่าสถานะไว้เหมือนกันและส่งคืนค่าตามค่าสถานะ

แก้ไข:

ในกรณีที่ฉันอยู่ในสถานการณ์ของคุณและฉันไม่ได้เขียนฟังก์ชันฉันอาจจะไปหา Variant 2 ฉันจะเก็บชื่อดัมมี่ไว้ที่นั่นเพื่อให้สามารถใช้พารามิเตอร์ในกรณีที่เกิดความต้องการได้ การแบ่งส่วนรายการจะมีค่าใช้จ่ายเล็กน้อย บางทีคุณสามารถสำรองสักสองสามไบต์เพื่อรับข้อมูลที่ไม่ต้องการ


-1 ฉันเดาว่าเขาไม่ได้นิยามฟังก์ชันดังนั้นจึงไม่สามารถเปลี่ยนสิ่งที่มันคืนมาได้ ฉันคิดว่าเขาหมายถึงเมื่อฟังก์ชันคืนค่า 3 ค่า แต่เขาใส่ใจเพียง 1 ในกรณีการใช้งานปัจจุบันของเขา
Craige

@Craige: ใช่ฉันหมายถึงฟังก์ชั่นที่ฉันไม่สามารถเปลี่ยนแปลงได้ - ฉันได้เพิ่มบันทึกย่อลงในคำถามของฉันเพื่อชี้แจงว่า
user49643

คุณแน่ใจเกี่ยวกับค่าใช้จ่ายหรือไม่ ฉันลองทดสอบ ipython ง่าย ๆ : %timeit a, _, _ = foo()เทียบกับ%timeit a = foo()[0]ซึ่งส่งผลให้ 123ns เทียบกับ 109ns นั่นคือการแบ่งส่วนจะเร็วกว่าค่าที่เปิดออกจริง ๆ หรือคุณมีสถานการณ์ที่เฉพาะเจาะจงในใจ?
user49643

2
สถานการณ์ที่เป็นไปได้อีกอย่างหนึ่งคือคุณไม่ต้องการค่าทั้งหมดสำหรับการโทรบางสาย
Keith Thompson
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.