เหตุใดจึงต้องใช้ฟังก์ชันว่าง


9

ฉันเริ่มเรียนรู้หลามและฉันสงสัยว่าทำไมฟังก์ชันว่างจึงจำเป็นต้องใช้ในภาษาการเขียนโปรแกรม

เช่นในหลาม:

def empty_func():
    pass

แม้ในเชลล์สคริปต์ฟังก์ชันว่างฟังก์ชันว่างมี

ความเข้าใจและคำถามของฉัน:

  1. ทำไมภาษาการเขียนโปรแกรมจำเป็นต้องมีฟังก์ชั่นที่ว่างเปล่า? มันเป็นเพียงการเล่นกับภาษาโปรแกรมหรือไม่มีอะไรที่สำคัญจริงๆ?

  2. หากมีวัตถุประสงค์ใครสามารถอธิบายกรณีการใช้งานหรือให้ตัวอย่างจริงของการใช้ฟังก์ชันว่างเปล่าได้หรือไม่

  3. หรือมีประเพณีของภาษาการเขียนโปรแกรมที่ช่วยให้ฟังก์ชั่นที่ว่างเปล่า?


แก้ไข (สิ่งที่ฉันได้จากการอ่านคำตอบของคุณ):

  • สำหรับขั้นตอนวิธีการร่างหรือฟังก์ชั่นบทคัดย่อ
  • สำหรับการส่งแบบฟอร์มโดยไม่ต้องดำเนินการใด ๆ
  • ตัวยึดสำหรับการดำเนินการบังคับบางอย่าง

1
สามารถใช้เป็น STUBS ได้หากการเรียกใช้โปรแกรมคาดว่าจะพบ / ใช้งานได้อย่างไรก็ตามคุณไม่ต้องการเปลี่ยนแปลงอะไรเลย
G.Rassovsky

คำตอบ:


5

ในภาษาเชลล์ของตระกูล Bourne :คำสั่งซึ่งไม่ได้ทำอะไรเลยมักใช้ในสองสถานการณ์:

  • ตัวยึดตำแหน่งสำหรับสิ่งที่คาดว่าจะมีคำสั่งบังคับเช่น

    while some_condtion
    do :
    done

    ตั้งแต่doต้องการอย่างน้อยหนึ่งคำสั่ง

  • ยกเลิกการโต้แย้ง แต่ทำผลข้างเคียงภายในรายการอาร์กิวเมนต์เช่น

    : ${myvar=foo}

ฉันแน่ใจว่ามีแอปพลิเคชั่นอื่น ๆ ที่ผู้เชี่ยวชาญเชลล์จะรู้ :)

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

def submit(callback=empty_func):
    ...

วิธีนี้หากcallbackไม่ได้ระบุไว้การส่งจะยังคงดำเนินต่อไป แต่จะไม่มีการดำเนินการเพิ่มเติม หากคุณใช้Noneเป็นค่าเริ่มต้นคุณจะต้องตรวจสอบอย่างชัดเจนว่ามีการโทรกลับNoneหรือไม่เพิ่มความวุ่นวายให้กับรหัส


1

ขึ้นอยู่กับว่าคุณยืนอยู่ตรงไหนในวงจรการพัฒนา แต่บางครั้งเมื่อร่างอัลกอริทึมคุณต้องการทำให้นามธรรมเกี่ยวกับบล็อกที่ซับซ้อนโดยไม่ต้องใช้มันในทันที

def full_algo():
  init_stuff()
  process_stuff()
  ...

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

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

init_filesystem();
access_files();
release_filesystem();

รหัสนี้จะทำงานกับหลาย ๆ แพลตฟอร์ม แต่บางแพลตฟอร์มอาจไม่ต้องการเริ่มต้นระบบไฟล์ จากนั้นการสืบทอดของคุณจะมีลักษณะเช่นนี้ (เสมือนกับ = 0 ใน C ++ หมายถึงคลาสที่ได้รับต้องใช้วิธีการเหล่านั้น):

class FileSystem{
  virtual void init_filesystem() = 0;
  virtual void access_files() = 0;
  virtual void release_filesystem() = 0;
};

จากนั้นการใช้งานเฉพาะของคลาสนี้ (อินเทอร์เฟซ) อาจไม่ทำอะไรเลยสำหรับบางวิธี อีกทางเลือกหนึ่งคลาสพื้นฐานสามารถประกาศวิธีการที่ว่างเปล่าสำหรับ init / release แทนที่จะประกาศพวกเขาเสมือน

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


0

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

มันจำเป็นในกรณีหลามเพราะมันใช้เยื้องบล็อกเครื่องหมายซึ่งแตกต่างจาก {}C-เช่นภาษาที่ใช้การจัดฟัน นี่หมายความว่าถ้าคุณไม่มีpassparser จะไม่สามารถบอกได้ว่าคุณตั้งใจจะเว้นว่างไว้หรือไม่หรือถ้าคุณลืม การรวมpassทำให้ parser ง่ายขึ้นมากและให้คำที่สะดวกในการค้นหาเมื่อคุณกำลังมองหาบล็อกที่ยังไม่ได้ใช้งาน


1
สำหรับโค้ดที่ยังไม่เสร็จการขว้างNotImplementedErrorเป็นวิธีแก้ปัญหาที่เพียงพอมากกว่าเนื่องจาก "ข้อผิดพลาดไม่ควรผ่านไปอย่างเงียบ ๆ " และการเรียกใช้ฟังก์ชันที่ไม่ได้ดำเนินการในโปรแกรมสดเป็นข้อผิดพลาด
ivan_pozdeev

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

0

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

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


ฉันใช้passตัวยึดตำแหน่งเป็นจำนวนมากเมื่อเขียนโค้ดโดยเฉพาะในชั้นเรียนเมื่อฉันต้องการให้บางสิ่งบางอย่างสามารถทำงานได้ก่อนที่ทุกอย่างจะเสร็จสมบูรณ์ มันเทียบเท่ากับ{}งูหลามของงูเหลือมซึ่งงูเหลือมไม่สามารถทำได้เนื่องจากไม่ใช้เหล็กดัดฟัน ในแง่นั้นทุกภาษาที่ฉันรู้อนุญาตให้มันเป็นเพียงสองสามอย่างที่pythonต้องการคำหลัก NOPแม้จะกลับมาในวันที่การชุมนุมที่เรามี
Gort the Robot

@StevenBurnap โดยปกติเมื่อฉันทำอะไรเช่นนั้นฉันจะรวมเฉพาะท้องถิ่นของ printf (">>> ประจำ XXX เรียกว่า \ n");
John R. Strohm
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.