การใช้ if-return-return หรือ if-else-return นั้นมีประสิทธิภาพมากกว่าหรือไม่


141

สมมติว่าผมมีคำสั่งด้วยif returnจากมุมมองประสิทธิภาพฉันควรใช้

if(A > B):
    return A+1
return A-1

หรือ

if(A > B):
    return A+1
else:
    return A-1

ฉันควรจะเลือกภาษาใดภาษาหนึ่งเมื่อใช้ภาษาที่รวบรวม (C) หรือภาษาสคริปต์ (Python)


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

5
การใช้คอมไพเลอร์ของคุณเพื่อจัดเรียงโค้ดของคุณเป็นขั้นตอนที่อันตรายและต้องใช้คอมไพเลอร์ที่ผิดพลาด ดีกว่าถ้าคุณรู้ว่าคุณต้องการให้รหัสของคุณทำอะไร!
Andrew

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

7
สิ่งนี้จะถูกปิดเพราะความเห็นได้อย่างไร? อาจเป็นความเห็นหลังจากที่คุณรู้ว่าไม่มีความแตกต่างระหว่างประสิทธิภาพทั้งสอง ฉันไม่ได้และฉันค่อนข้างมั่นใจว่าผู้คนจำนวนมากก็ไม่ได้
Jorge Leitao

1
แม้ว่าคำถามจะได้รับความนิยม แต่ก็ไม่สามารถตอบได้อย่างถูกต้องหากไม่มีภาษาที่เฉพาะเจาะจงหรือไม่เช่นนั้นการตอบคำถามทุกภาษาจะยาวเกินไปสำหรับรูปแบบนี้
Emile Bergeron

คำตอบ:


195

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

ประสิทธิภาพของทั้งสองรูปแบบเทียบเคียงได้รหัสเครื่องต้นแบบจะต้องทำการกระโดดหากifเงื่อนไขเป็นเท็จอยู่ดี

โปรดทราบว่า Python สนับสนุนไวยากรณ์ที่ช่วยให้คุณใช้returnคำสั่งเดียวในกรณีของคุณ:

return A+1 if A > B else A-1

32
C ก็รองรับเช่นกัน return (A>B)?A+1:A-1;อย่างไรก็ตามไม่มีการเพิ่มประสิทธิภาพอย่างแน่นอนจากการเขียนโค้ดเช่นนี้ สิ่งที่เราทำได้คือทำให้โค้ดสับสนอ่านไม่ได้และในบางกรณีมีความเสี่ยงที่จะโปรโมตประเภทโดยนัย
Lundin

47
@Lundin งงงวย? อ่านไม่ได้? เฉพาะสำหรับผู้ที่ไม่ทราบผู้ประกอบการที่สาม
glglgl

6
@Lundin หลังจากการโต้แย้งนี้<เป็นการปฏิบัติที่ไม่ดีเพราะ-1 < 1uให้ผลลัพธ์ที่ไม่คาดคิด
glglgl

3
@glglgl: ไม่เพราะผู้คนคาดหวังว่าตัวดำเนินการ?: จะทำงานเป็น if-else ซึ่งไม่เป็นความจริง หากใครบางคนจะเขียนโค้ดอย่าง-1 < 1uที่ฉันสงสัยพวกเขาจะสังเกตเห็นข้อผิดพลาดได้อย่างง่ายดาย ผู้คนจำนวนมากจะเขียนโค้ดบางเวอร์ชันที่ฉันโพสต์ ฉันเห็นข้อบกพร่องดังกล่าวบ่อยเกินไปในรหัสการผลิตเพื่อเชื่อถือตัวดำเนินการ:: เช่นเดียวกับกฎทั่วไปหากภาษาให้สองวิธีที่แตกต่างกันในการทำสิ่งเดียวกันให้ใช้วิธีใดวิธีหนึ่งเท่านั้นอย่าสุ่มเลือกทั้งสองแบบขึ้นอยู่กับอารมณ์ของคุณ
Lundin

6
@Lundin ที่เป็นข้อโต้แย้งในการระวัง?: ใน C แต่คุณดูเหมือนจะบอกว่ามันใช้กับ Python เช่นกัน คุณสามารถชี้ไปที่ตัวอย่างที่ใช้ ternary ใน Python นำไปสู่ผลลัพธ์ที่ไม่คาดคิดได้หรือไม่?
lvc

33

จากคู่มือสไตล์ของ Chromium :

อย่าใช้อย่างอื่นหลังจากส่งคืน:

# Bad
if (foo)
  return 1
else
  return 2

# Good
if (foo)
  return 1
return 2

return 1 if foo else 2

1
ขอบคุณ +1 ฉันขอถามได้ไหมว่าทำไมไม่ใช้อย่างอื่นหลังจากส่งคืน
ทิม

1
if-else เทียบเท่ากับการใช้งานได้ อย่างอื่นนั้นไม่จำเป็น
skeller88

17
ฉันประหลาดใจเพราะครั้งแรกดูเหมือนชัดเจนมากขึ้นและดีขึ้น
ทิม

4
คุณสามารถทำกรณีที่เหมาะสมสำหรับทั้ง สิ่งที่สำคัญที่สุดในการตัดสินใจ IMO นี้คือการให้สอดคล้องภายในรหัสฐาน
skeller88

2
คุณอาจพบว่าในกรณีส่วนใหญ่ที่if-else-returnสาขาแทบจะไม่เท่ากัน (ถ้าเป็นเช่นนั้นคุณควรทำการปรับโครงสร้างต่อไปไม่ว่าจะใช้switchโครงสร้างหรือ Python ให้ระบุ dict / ใช้ callable / etc) ดังนั้นเกือบทุกif-else-returnกรณีของข้อระวังและผู้ที่มีเสมอทดสอบ (เยาะเย้ยการแสดงออกผ่านการทดสอบ) elseโดยไม่ต้อง
cowbert

5

เกี่ยวกับรูปแบบการเข้ารหัส:

มาตรฐานการเข้ารหัสส่วนใหญ่ไม่ว่าภาษาใดจะห้ามใช้คำสั่งคืนหลายคำสั่งจากฟังก์ชั่นเดียวว่าเป็นการฝึกฝนที่ไม่ดี

(แม้ว่าโดยส่วนตัวแล้วฉันจะบอกว่ามีหลายกรณีที่ข้อความสั่งคืนหลายรายการมีเหตุผล: ข้อความ / ตัวแยกวิเคราะห์โปรโตคอลข้อมูลฟังก์ชั่นที่มีการจัดการข้อผิดพลาดมากมาย ฯลฯ )

ฉันทามติจากมาตรฐานการเข้ารหัสของอุตสาหกรรมเหล่านั้นคือนิพจน์ควรเขียนเป็น:

int result;

if(A > B)
{
  result = A+1;
}
else
{
  result = A-1;
}
return result;

เกี่ยวกับประสิทธิภาพ:

ตัวอย่างข้างต้นและสองตัวอย่างในคำถามล้วนมีความเท่าเทียมกันอย่างสมบูรณ์ในแง่ของประสิทธิภาพ รหัสเครื่องในกรณีเหล่านี้ทั้งหมดต้องเปรียบเทียบ A> B จากนั้นแยกสาขาเป็นการคำนวณ A + 1 หรือ A-1 จากนั้นจัดเก็บผลลัพธ์ของการลงทะเบียน CPU หรือในสแต็ก

แก้ไข:

แหล่งที่มา:

  • MISRA-C: 2004 กฎ 14.7 ซึ่งจะอ้างอิง ... :
  • IEC 61508-3 ส่วนที่ 3 ตาราง B.9
  • IEC 61508-7 C.2.9

37
คุณแน่ใจหรือว่าศาสนาที่มีผลตอบแทนแบบเดี่ยวติดมาตรฐานการเข้ารหัสมากที่สุด? นั่นจะน่ากลัว
Daniel Fischer

7
ฉันจะบอกว่ากฎไม่สมเหตุสมผลเวลาส่วนใหญ่ ฉันมักจะพบโค้ดอ่านได้ง่ายขึ้นและง่ายต่อการติดตามผลตอบแทนตามจุดที่เหมาะสม แต่นั่นเป็นเพียงฉัน อย่างไรก็ตามฉันคิดว่าตามมาตรฐานการเข้ารหัสของ บริษัท / โครงการไม่ใช่สิ่งต่าง ๆ เช่น MISRA ที่มิฉะนั้นใบสั่งยาที่งี่เง่าอาจมีบุญบ้าง ฉันหวังว่าส่วนใหญ่ไม่ได้ซื้อเป็นแนวคิดจุดทางออกเดียว
Daniel Fischer

3
@DanielFischer: ในมาตรฐานการเข้ารหัส C ตาม MISRA ที่ฉันออกแบบสำหรับ บริษัท ของฉันฉันมีกฎ "ฟังก์ชั่นจะต้องมีจุดทางออกเดียวที่จุดสิ้นสุดของฟังก์ชั่นเว้นแต่จุดออกเดียวทำให้รหัส อ่านได้น้อย " ดังนั้นมันคือ MISRA-C แต่มีข้อยกเว้นกฎ หากคุณเขียนฟังก์ชันตัวแยกวิเคราะห์ขั้นสูงซึ่งสามารถส่งคืนได้จะบอกว่ามีข้อผิดพลาดที่แตกต่างกันถึง 10 ระดับระดับของการจัดฟันแบบซ้อนจะทำให้โค้ดอ่านไม่ได้อย่างสมบูรณ์ - ในกรณีเช่นนี้
Lundin

6
ดูคำถาม SO นี้สำหรับการสนทนาและลิงค์เพิ่มเติมเพื่อการอภิปรายเพิ่มเติมเกี่ยวกับปัญหา single-exit-point นอกจากนี้กฎเดียวออกจากจุดที่เป็นสมัยเก่าและมากเกินไป "engineeringy" งูใหญ่โดยเฉพาะส่งเสริมการ"แบนจะดีกว่าที่ซ้อนกัน" มุมมองและวางreturn ที่ใดก็ตามที่มันเกิดขึ้นต้องมีความชัดเจนเป็นวิธีที่เป็นสำนวนที่จะทำมันในหลาม
John Y

1
@percebus ฉันเห็นด้วยอย่างสมบูรณ์และความซับซ้อนของวัฏจักรเป็นข้อโต้แย้งที่ดีสำหรับการกลับมาครั้งเดียว และฉันได้รับ poking คณะกรรมการ MISRA เกี่ยวกับเรื่องนี้หลายครั้งเช่นเห็นนี้ อย่างน้อยกฎก็ถูกลดระดับเป็นคำแนะนำใน MISRA-C: 2012
Lundin

3

ด้วยคอมไพเลอร์ที่สมเหตุสมผลคุณควรสังเกตความแตกต่าง ควรจะคอมไพล์รหัสเครื่องที่เหมือนกันเนื่องจากเทียบเท่า


2

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

โดยการตั้งค่าฉันใช้:

return A+1 if (A > B) else A-1

เนื่องจากเป็นไปตามข้อตกลงที่ดีของการมีคำสั่งส่งคืนเดียวเป็นคำสั่งสุดท้ายในฟังก์ชั่น (ดังที่ได้กล่าวไว้แล้ว) และกระบวนทัศน์การเขียนโปรแกรมที่ใช้งานได้ดีในการหลีกเลี่ยงผลลัพธ์กลางที่จำเป็น

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

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


1
หากผู้ใช้กำลังลงคะแนนคำตอบของฉันฉันจะขอบคุณความคิดเห็นว่าทำไมพวกเขาคิดว่าฉันผิด
Stephen Ellwood

ฉันอาจจะเป็นเพียงบรรทัดก่อนที่จะทำให้มัน 1 บรรทัดต่อคำสั่งเพื่อวัตถุประสงค์ในการอ่าน var n = 1 if (A > B) else -1 return A+n
รู้

@percebus ในบางกรณีฉันจะยอมรับว่าชื่อตัวแปรสามารถปรับปรุงความหมายได้หรือไม่ ตัวอย่างเช่น: 'code' move_x = 1 ถ้า my_x <ฝ่ายตรงข้ามอื่น ๆ -1 # เคลื่อนไปหาคู่ต่อสู้
Stephen Ellwood

BTW ฉัน upvoted คำตอบของคุณจริง หากคุณเห็นว่าคำตอบของฉันค่อนข้างคล้ายกัน
รู้

2

ฉันหลีกเลี่ยงการelseบล็อกส่วนตัวเมื่อเป็นไปได้ ดูแคมเปญต่อต้านถ้า

นอกจากนี้พวกเขาไม่คิดค่าใช้จ่าย 'พิเศษ' สำหรับสายคุณรู้ว่า: p

"ง่ายดีกว่าซับซ้อน" & "การอ่านเป็นกษัตริย์"

delta = 1 if (A > B) else -1
return A + delta

2
ทำไมถึงลงคะแนน? คือคำตอบ 'pythonic' คุณอาจไม่คิดว่ามันเป็นคำตอบที่ต้องการ แต่ไม่ใช่สิ่งที่ไม่ถูกต้อง ฉันกำลังติดตาม KISS Principle ด้วยเช่นกันen.wikipedia.org/wiki/KISS_principle
recognbus

3
ฉันยกระดับคำตอบของคุณเนื่องจากคะแนนของฉันนั้นง่ายต่อการอ่านและเรียบง่าย โดยส่วนตัวแล้วฉันพบว่ามันน่ารังเกียจคือมีคนโหวตฉันโดยที่ไม่รู้ตัวว่าทำไมคำตอบของฉันจึงเป็นลบอย่างแข็งขัน
Stephen Ellwood

1
ไม่เคยได้ยินมาก่อนเกี่ยวกับแคมเปญ Anti-if แต่สามารถเข้าใจได้ว่าทำไม ifs อาจเป็นอันตราย ฉันพยายาม จำกัด จำนวนของรหัสที่ล้อมรอบด้วยคำสั่ง if และพยายามเขียนต้นไม้ elif เพื่อใช้ dict สิ่งนี้กำลังได้รับเล็กน้อยนอกหัวข้อแม้ว่า
Stephen Ellwood

1
@StephenEllwood การใช้dicts เพื่อหลีกเลี่ยง diffs เป็นความคิดที่ไม่ดีมาก ๆ
Bachsau

@Bachsau คุณอาจพูดถูก ฉันไม่ต้องกังวลกับการทำงานเนื่องจากสคริปต์ของฉันทำงานในไม่กี่วินาที สำหรับฉันการอ่านมักจะสำคัญกว่าประสิทธิภาพ เนื่องจากฉันไม่ใช่โปรแกรมเมอร์เต็มเวลา พวกเขาเป็นเพียงหนทางสู่จุดจบ
Stephen Ellwood

1

เวอร์ชั่น A นั้นง่ายกว่าและนั่นเป็นสาเหตุที่ฉันจะใช้มัน

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


1

ฉันรู้ว่าคำถามถูกติดแท็กไพ ธ อน แต่มันพูดถึงภาษาไดนามิกดังนั้นคิดว่าฉันควรพูดถึงว่าในทับทิมถ้าคำสั่งที่จริงมีประเภทกลับเพื่อให้คุณสามารถทำสิ่งที่ชอบ

def foo
  rv = if (A > B)
         A+1
       else
         A-1
       end
  return rv 
end

หรือเพราะมันยังมีผลตอบแทนโดยปริยายเพียง

def foo 
  if (A>B)
    A+1
  else 
    A-1
  end
end

ซึ่งได้รับการแก้ไขปัญหาสไตล์ที่ไม่มีผลตอบแทนหลายอย่างค่อนข้าง

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