ทำไมไพ ธ อนไม่ต้องการคอมไพเลอร์?


29

แค่สงสัย (ตอนนี้ฉันเริ่มต้นด้วย C ++ ที่ต้องการคอมไพเลอร์) ทำไม Python ไม่ต้องการคอมไพเลอร์?

ฉันเพิ่งป้อนรหัสบันทึกเป็นผู้บริหารและเรียกใช้ ใน C ++ ฉันต้องสร้างและสิ่งสนุกอื่น ๆ ทั้งหมด


4
Python เป็นเพียงภาษาที่มีการใช้งานมากมาย Iron Python รวบรวมในลักษณะเดียวกับ C # และ C ++ ที่คอมไพล์แล้วและอาจมีการใช้งานอื่น ๆ เช่นนั้น
งาน

1
C # และ C ++ นั้นไม่ได้ถูกคอมไพล์ด้วยวิธีเดียวกัน - แม้ว่าคุณสามารถยืนยันได้ว่าทั้งคู่นั้นจบลงด้วยคำแนะนำของเครื่องจักรในที่สุด แต่ถ้าคุณทำเช่นนั้น
gbjbaanb

7
@gbjbaanb แต่ภาษาอังกฤษไม่คอมไพล์อีกครั้งและการวิเคราะห์ความหมายของประโยคหนึ่งอาจให้ผลลัพธ์ที่ถูกต้องเท่ากันสองรายการและข้างต้นสามารถอ่านได้เนื่องจาก "ไพ ธ อนเหล็กถูกคอมไพล์เช่นเดียวกับ C # และ C ++ ถูกคอมไพล์"
Rune FS

คุณใช้แพลตฟอร์ม / ซอฟต์แวร์ใดในการเขียนรหัส Python ของคุณ หากคุณเขียนไฟล์. py ไฟล์นั้นจะไม่สามารถเรียกใช้งานได้ มันยังคงเป็นไฟล์รหัสต้นฉบับ จากบรรทัดคำสั่งคุณกำลังใช้pythonคำสั่งเพื่อแปลไฟล์. py หรือถ้าคุณใช้ IDLE หรือ Eclipse IDE จะทำเพื่อคุณ
Rick Henderson

คำตอบ:


68

Python มีผู้แปล! คุณไม่ได้สังเกตเพราะมันทำงานโดยอัตโนมัติ คุณสามารถบอกได้ว่ามันมีแม้ว่า: ดูที่.pyc(หรือ.pyoถ้าคุณมีการเพิ่มประสิทธิภาพเปิด) importไฟล์ที่สร้างขึ้นสำหรับโมดูลที่คุณ

นอกจากนี้ยังไม่ได้รวบรวมรหัสของเครื่องดั้งเดิม แต่จะรวบรวมรหัสไบต์ที่ใช้โดยเครื่องเสมือนแทน เครื่องเสมือนเป็นโปรแกรมที่คอมไพล์แล้ว นี่คล้ายกับวิธีการทำงานของ Java; ที่คล้ายกันจริงๆแล้วมีตัวแปร Python ( Jython ) ที่รวบรวมรหัสไบต์ของ Java Virtual Machine แทน! นอกจากนี้ยังมีIronPythonซึ่งรวมเข้ากับ CLR ของ Microsoft (ใช้โดย. NET) (บางครั้งคอมไพเลอร์โค้ดไบต์ไพ ธ อนบางครั้งเรียกว่า CPython เพื่อแยกแยะจากทางเลือกเหล่านี้)

C ++ ต้องเปิดเผยกระบวนการรวบรวมเพราะภาษานั้นไม่สมบูรณ์; มันไม่ได้ระบุทุกสิ่งที่ตัวเชื่อมโยงจำเป็นต้องรู้ในการสร้างโปรแกรมของคุณและไม่สามารถระบุตัวเลือกการคอมไพล์แบบพกพาได้ (ตัวแปลบางตัวช่วยให้คุณสามารถใช้งาน#pragmaได้ แต่นั่นไม่ใช่มาตรฐาน) ดังนั้นคุณต้องทำงานที่เหลือด้วย makefiles และ auto นรก (autoconf / automake / libtool) นี่เป็นเพียงส่วนที่หลงเหลือจากวิธีการที่ C ทำ และ C ทำอย่างนั้นเพราะมันทำให้คอมไพเลอร์เรียบง่ายซึ่งเป็นหนึ่งในเหตุผลหลักที่มันเป็นที่นิยม (ใคร ๆ ก็สามารถคอมไพล์คอมไพล์ C ในยุค 80 ได้)


บางสิ่งที่อาจส่งผลต่อการดำเนินการของตัวแปลหรือตัวเชื่อมโยง แต่ไม่ได้ระบุไว้ในไวยากรณ์ของ C หรือ C ++:

  • การแก้ปัญหาการพึ่งพา
  • ข้อกำหนดไลบรารีภายนอก (รวมถึงลำดับการขึ้นต่อกัน)
  • ระดับเครื่องมือเพิ่มประสิทธิภาพ
  • การตั้งค่าคำเตือน
  • รุ่นข้อกำหนดภาษา
  • การแมป linker (ส่วนใดไปที่ใดในโปรแกรมสุดท้าย)
  • สถาปัตยกรรมเป้าหมาย

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

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

สิ่งเหล่านี้สามารถตั้งค่าได้#pragmaหลายอย่าง แต่นี่ไม่ใช่มาตรฐานและฉันพูดถึงมาตรฐาน ทุกสิ่งเหล่านี้ทำได้ระบุได้โดยมาตรฐาน แต่ไม่ได้อยู่ในความสนใจของความเข้ากันได้ย้อนหลัง ภูมิปัญญาที่แพร่หลายคือการที่ makefiles และ IDEs ไม่พังดังนั้นอย่าแก้ไขมัน

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


3
การใช้งาน C ของ Python คือCPython , Cythonนั้นแตกต่างกัน
เกร็กฮิวกิล

4
เหตุผลอื่น ๆ ที่ C คอมไพล์ไปยังรหัสเครื่องนั้นมีวัตถุประสงค์เพื่อให้เป็นแอสเซมเบลอร์เล็กน้อยที่ได้รับเกียรติเพราะล่าม bytecode นั้นไม่สามารถทำได้ทางเทคนิคบนฮาร์ดแวร์ที่พวกเขามีและเพราะหนึ่งในภารกิจที่สำคัญที่สุดคือ
tdammers

2
@BillyONeal โดยมีข้อยกเว้นหนึ่งข้อใหญ่ที่ใน c / c ++ คุณในฐานะโปรแกรมเมอร์ต้องทำสิ่งต่าง ๆ ในลักษณะที่แน่นอน (ไม่ว่าจะเป็นไฟล์ makefiles หรือการถ่ายโอนข้อมูลทุกอย่างใน blob เดียวกัน) ใน python คุณแค่ทำงานและคอมไพเลอร์ร่วมกับ VM ดูแลส่วนที่เหลือ
Rune FS

3
"C ++ ต้องเปิดเผยกระบวนการรวบรวมเพราะภาษานั้นไม่สมบูรณ์"เอ่ออะไร ??
การแข่งขัน Lightness กับโมนิก้า

3
คุณอ่านส่วนหลังจากนั้นใช่ไหม "ไม่ได้ระบุทุกสิ่งที่ตัวเชื่อมโยงจำเป็นต้องรู้เพื่อสร้างโปรแกรมของคุณและไม่สามารถระบุตัวเลือกการคอมไพล์ได้" คุณไม่สามารถสร้างไฟล์ C ++ ใด ๆเพียงแค่ส่งไปยังคอมไพเลอร์ บ่อยครั้งที่คุณต้องให้ข้อมูลเมตาเช่นการรวบรวมธงรวมถึงเส้นทาง ฯลฯ ข้อมูลเมตานี้ไม่ได้ระบุไว้โดยมาตรฐานและไม่ได้พกพาซึ่งเป็นเหตุผลที่เราต้องลากในสิ่งอื่น ๆ เช่นทำ, cmake, Visual Studio หรืออะไรก็ตาม เสร็จงาน ดังนั้นมาตรฐานจึงต้องเรียกสิ่งต่าง ๆ เช่นเดียวกับในหน่วยรวบรวมและอื่น ๆ เป็นโปรแกรมกว้าง
Mike DeSimone

7

Python เป็นภาษาที่ตีความ ซึ่งหมายความว่ามีซอฟต์แวร์ในคอมพิวเตอร์ของคุณที่อ่านรหัส Python และส่ง "คำแนะนำ" ไปยังเครื่อง บทความวิกิพีเดียในการแปลภาษาอาจจะเป็นที่สนใจ

เมื่อภาษาเช่น C ++ (ภาษาที่คอมไพล์) ถูกรวบรวมหมายความว่ามันถูกแปลงเป็นรหัสเครื่องเพื่อให้ฮาร์ดแวร์อ่านได้โดยตรงเมื่อดำเนินการ บทความวิกิพีเดียภาษาเรียบเรียงอาจให้ความคมชัดที่น่าสนใจ


21
ไม่มีสิ่งใดที่แปลหรือเรียบเรียงเป็นภาษา ภาษาคือชุดของกฎทางคณิตศาสตร์ที่เป็นนามธรรม ภาษาไม่ได้แปลหรือแปลความหมาย ภาษาเพียงคือ การรวบรวมและการตีความเป็นลักษณะของคอมไพเลอร์หรือล่าม (duh!) ไม่ใช่ภาษา ทุกภาษาสามารถนำไปใช้กับคอมไพเลอร์และทุกภาษาสามารถนำไปใช้กับล่าม ภาษาส่วนใหญ่มีทั้งการรวบรวมและตีความการใช้งาน มีล่ามสำหรับ C ++ และมีคอมไพเลอร์สำหรับ Python (อันที่จริงแล้วการใช้งาน Python ที่มีอยู่ในปัจจุบันทั้งหมดมีคอมไพเลอร์)
Jörg W Mittag

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

10
@ JörgWMittag: คุณพูดถูก อย่างไรก็ตามภาษาส่วนใหญ่ได้รับการออกแบบสำหรับบริบทตีความหรือรวบรวมเต็ม การเขียนล่ามสำหรับ GW BASIC หรือ Common LISP นั้นง่ายกว่าการเขียนล่ามสำหรับพูด C ++ หรือ C # Python สูญเสียจุดขายจำนวนมากโดยไม่มีสภาพแวดล้อมแบบโต้ตอบ การเขียนคอมไพเลอร์สำหรับ PHP นั้นค่อนข้างยากและอาจไม่มีประสิทธิภาพอย่างน่ากลัวเนื่องจากตัวประมวลผลที่คอมไพล์จะต้องมีตัวแปล PHP ทั้งหมดเนื่องจาก eval () และโครงสร้างที่คล้ายกัน - เราอาจโต้แย้งว่า
tdammers

2
@ ผู้ส่งข่าวใช่ เราสามารถใช้ "ภาษาที่คอมไพล์" เพื่อแปลความหมายว่า "ภาษาที่รวบรวมมักจะ" แต่นั่นก็ไม่ได้หมายความว่า PHP, Java, Python, Lua และ C # จะถูกนำไปใช้เป็นคอมไพเลอร์ของ bytecode ภาษาทั้งหมดเหล่านี้มีการใช้งานของ JIT สำหรับพวกเขาด้วย ดังนั้นจริงๆคุณไม่สามารถเรียกภาษาเหล่านี้รวบรวมและตีความบางอย่างเพราะพวกเขามีกลยุทธ์การใช้งานเดียวกัน
Winston Ewert

2
@BillyONeal ไม่เป็นความจริงอย่างน้อยสำหรับ python คุณสามารถแจกจ่ายไพ ธ อนรหัสและเรียกใช้โดยไม่มีแหล่งที่มา แต่เป็นความจริงที่ว่าคุณไม่สามารถแจกจ่ายไพ ธ อนได้หากไม่มีคอมไพเลอร์
Winston Ewert

5

ภาษาที่คอมไพล์บางภาษาเท่านั้นที่มีวัฏจักรในการแก้ไขรวบรวมลิงค์

สิ่งที่คุณกำลังประสบคือคุณสมบัติ / ข้อ จำกัด ของ C ++ (หรือการใช้งาน C ++ อย่างน้อย)

ในการทำสิ่งใดคุณต้องเก็บรหัสไว้ในไฟล์และสร้างภาพเสาหินโดยกระบวนการที่เรียกว่าการลิงก์

โดยเฉพาะอย่างยิ่งมันเป็นกระบวนการเชื่อมโยงเสาหินซึ่งเป็นความเข้าใจผิดสำหรับความแตกต่างระหว่างการรวบรวมและการตีความ

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

คุณพูดว่า "โหลดโมดูลนี้ใหม่" และโหลดแหล่งข้อมูลและแปลความหมายหรือรวบรวมมันขึ้นอยู่กับสวิตช์โหมดบางโหมด

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

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


2

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

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

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


1

ภาษาการเขียนโปรแกรมทั้งหมดต้องการการแปลจากแนวคิดของมนุษย์เป็นรหัสเครื่องเป้าหมาย แม้แต่ภาษาแอสเซมบลีต้องแปลเป็นรหัสเครื่อง การแปลนั้นมักจะเกิดขึ้นในเฟสต่อไปนี้:

ขั้นตอนที่ 1: การวิเคราะห์และการแปล (การแยกวิเคราะห์) เป็นรหัสระดับกลาง ขั้นตอนที่ 2: การแปลรหัสกลางเป็นรหัสเครื่องเป้าหมายพร้อมตัวยึดสถานที่สำหรับการอ้างอิงภายนอก ขั้นตอนที่ 3: การแก้ปัญหาการอ้างอิงภายนอกและการบรรจุลงในโปรแกรมปฏิบัติการของเครื่อง

การแปลนี้มักจะเรียกว่าการรวบรวมล่วงหน้าและ "Just in time" (JIT) หรือการรวบรวมเวลาทำงาน

ภาษาเช่น C, C ++, COBOL, Fortran, Pascal (ไม่ใช่ทั้งหมด) และแอสเซมบลีเป็นภาษาที่คอมไพล์แล้วที่สามารถดำเนินการโดยตรงโดยระบบที่ดำเนินการโดยตรงโดยไม่จำเป็นต้องใช้ล่าม

ภาษาเช่น Java, BASIC, C # และ Python ถูกตีความ พวกเขาทั้งหมดใช้รหัสกลางที่สร้างขึ้นในระยะที่ 1 แต่บางครั้งจะแตกต่างกันในวิธีที่พวกเขาแปลเป็นรหัสเครื่อง แบบฟอร์มที่ง่ายที่สุดใช้รหัสกลางนั้นเพื่อเรียกใช้งานรหัสประจำเครื่องที่ทำงานตามที่คาดหวัง คนอื่น ๆ จะรวบรวมรหัสกลางลงไปที่รหัสเครื่องและทำการแก้ไขการอ้างอิงภายนอกในระหว่างรันไทม์ เมื่อรวบรวมแล้วจะสามารถดำเนินการได้ทันที รหัสเครื่องจะถูกเก็บไว้ในแคชของรหัสเครื่องที่นำมาใช้ซ้ำซึ่งรวบรวมไว้ก่อนหน้าซึ่งสามารถนำกลับมาใช้ใหม่ได้ในภายหลังหากจำเป็นต้องใช้ฟังก์ชันอีกครั้งในภายหลัง หากฟังก์ชั่นแคชแล้วล่ามไม่จำเป็นต้องรวบรวมอีกครั้ง

ภาษาระดับสูงที่ทันสมัยส่วนใหญ่ตกอยู่ในหมวดหมู่ตีความ (กับ JIT) ส่วนใหญ่เป็นภาษาเก่าเช่น C & C ++ ที่ถูกคอมไพล์ล่วงหน้า

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