ฉันกำลังพยายามค้นหาว่าเหตุใดการใช้global
จึงถือว่าเป็นการปฏิบัติที่ไม่ดีใน python (และในการเขียนโปรแกรมโดยทั่วไป) ใครสามารถอธิบาย? ลิงก์ที่มีข้อมูลเพิ่มเติมจะได้รับการชื่นชม
ฉันกำลังพยายามค้นหาว่าเหตุใดการใช้global
จึงถือว่าเป็นการปฏิบัติที่ไม่ดีใน python (และในการเขียนโปรแกรมโดยทั่วไป) ใครสามารถอธิบาย? ลิงก์ที่มีข้อมูลเพิ่มเติมจะได้รับการชื่นชม
คำตอบ:
สิ่งนี้ไม่เกี่ยวข้องกับ Python ตัวแปรส่วนกลางไม่ถูกต้องในภาษาโปรแกรมใด ๆ
อย่างไรก็ตามค่าคงที่ทั่วโลกไม่ได้เป็นแนวคิดเดียวกับตัวแปรทั่วโลก ; ค่าคงที่ทั่วโลกไม่เป็นอันตรายอย่างสมบูรณ์ ใน Python ความแตกต่างระหว่างทั้งสองนั้นเป็นไปตามแบบแผน: CONSTANTS_ARE_CAPITALIZED
และglobals_are_not
.
เหตุผลที่ตัวแปรทั่วโลกที่ไม่ดีที่พวกเขาช่วยฟังก์ชั่นที่จะมีการซ่อน (ไม่ใช่ที่เห็นได้ชัดน่าแปลกใจยากที่จะตรวจสอบยากที่จะวินิจฉัย) ผลข้างเคียงที่นำไปสู่การเพิ่มขึ้นของความซับซ้อนที่อาจนำไปสู่รหัสปาเก็ตตี้
อย่างไรก็ตามการใช้สถานะทั่วโลกอย่างมีเหตุผลนั้นเป็นที่ยอมรับได้ (เช่นเดียวกับสถานะท้องถิ่นและความสามารถในการเปลี่ยนแปลง) แม้ในการเขียนโปรแกรมเชิงฟังก์ชันไม่ว่าจะเป็นการเพิ่มประสิทธิภาพอัลกอริทึมความซับซ้อนที่ลดลงการแคชและการบันทึกหรือการใช้งานจริงของโครงสร้างการย้ายที่มาจาก codebase ที่จำเป็นส่วนใหญ่
สรุปแล้วคำถามของคุณสามารถตอบได้หลายวิธีดังนั้นทางออกที่ดีที่สุดของคุณคือ Google "ทำไมตัวแปรทั่วโลกถึงไม่ดี" ตัวอย่างบางส่วน:
หากคุณต้องการเจาะลึกและค้นหาว่าเหตุใดผลข้างเคียงจึงเป็นเรื่องเกี่ยวกับและสิ่งที่ทำให้กระจ่างอื่น ๆ อีกมากมายคุณควรเรียนรู้ Functional Programming:
ใช่ตามทฤษฎีแล้วโลก (และ "รัฐ" โดยทั่วไป) เป็นสิ่งชั่วร้าย ในทางปฏิบัติหากคุณดูไดเร็กทอรีแพ็กเกจของ python คุณจะพบว่าโมดูลส่วนใหญ่ในนั้นเริ่มต้นด้วยการประกาศทั่วโลกจำนวนมาก เห็นได้ชัดว่าผู้คนไม่มีปัญหากับพวกเขา
โดยเฉพาะอย่างยิ่งสำหรับ python การมองเห็นของ globals จะ จำกัด อยู่ที่โมดูลดังนั้นจึงไม่มี globals "จริง" ที่ส่งผลกระทบต่อโปรแกรมทั้งหมดซึ่งทำให้เป็นอันตรายน้อยลง อีกประเด็นหนึ่ง: ไม่มีconst
ดังนั้นเมื่อคุณต้องการค่าคงที่คุณต้องใช้ global
ในทางปฏิบัติของฉันหากฉันเกิดการแก้ไข global ในฟังก์ชันฉันมักจะประกาศด้วยglobal
แม้ว่าในทางเทคนิคจะไม่จำเป็นก็ตามเช่นใน:
cache = {}
def foo(args):
global cache
cache[args] = ...
สิ่งนี้ทำให้การจัดการของลูกโลกง่ายขึ้นในการติดตาม
ความคิดเห็นส่วนตัวในหัวข้อนี้คือการที่มีการใช้ตัวแปรส่วนกลางในตรรกะของฟังก์ชันหมายความว่าโค้ดอื่น ๆ สามารถเปลี่ยนแปลงตรรกะและผลลัพธ์ที่คาดหวังของฟังก์ชันนั้นซึ่งจะทำให้การดีบักทำได้ยากมาก (โดยเฉพาะในโครงการใหญ่ ๆ ) และจะทำให้การทดสอบยากขึ้น เช่นกัน.
นอกจากนี้หากคุณพิจารณาคนอื่น ๆ ที่อ่านโค้ดของคุณ (ชุมชนโอเพนซอร์สเพื่อนร่วมงาน ฯลฯ ) พวกเขาจะมีช่วงเวลาที่ยากลำบากในการพยายามทำความเข้าใจว่าตัวแปรส่วนกลางถูกตั้งค่าที่ไหนมีการเปลี่ยนแปลงที่ไหนและสิ่งที่คาดหวังจากตัวแปรส่วนกลางนี้เมื่อเทียบกับ ไปยังฟังก์ชันที่แยกได้ซึ่งสามารถกำหนดฟังก์ชันการทำงานได้โดยการอ่านนิยามฟังก์ชันเอง
ฉันเชื่อว่าโค้ดที่สะอาดและ (เกือบ) ปราศจากบั๊กควรมีฟังก์ชันที่บริสุทธิ์ที่สุดเท่าที่จะเป็นไปได้ (ดูฟังก์ชันที่บริสุทธิ์ ) ฟังก์ชันบริสุทธิ์คือฟังก์ชันที่มีเงื่อนไขดังต่อไปนี้:
การมีตัวแปรส่วนกลางกำลังละเมิดอย่างน้อยหนึ่งในข้างต้นหากไม่ใช่ทั้งสองอย่างเป็นรหัสภายนอกอาจทำให้เกิดผลลัพธ์ที่ไม่คาดคิด
คำจำกัดความที่ชัดเจนอีกประการหนึ่งของฟังก์ชันบริสุทธิ์: "ฟังก์ชัน Pure คือฟังก์ชันที่รับอินพุตทั้งหมดเป็นอาร์กิวเมนต์ที่ชัดเจนและสร้างเอาต์พุตทั้งหมดเป็นผลลัพธ์ที่ชัดเจน " [1] การมีตัวแปรส่วนกลางจะละเมิดความคิดของฟังก์ชันบริสุทธิ์เนื่องจากอินพุตและอาจเป็นหนึ่งในเอาต์พุต (ตัวแปรส่วนกลาง) ไม่ได้รับหรือส่งคืนอย่างชัดเจน
เพิ่มเติมเกี่ยวกับว่าถ้าคุณพิจารณาหน่วยทดสอบและหลักการแรก ( Fทดสอบ AST, ผมทดสอบ ndependent, R epeatable, Sเอลฟ์การตรวจสอบและT imely) อาจจะละเมิดหลักการทดสอบอิสระ (ซึ่งหมายถึงว่าการทดสอบไม่ได้ขึ้นอยู่ ซึ่งกันและกัน).
การมีตัวแปรส่วนกลาง (ไม่เสมอไป) แต่ในกรณีส่วนใหญ่ (อย่างน้อยที่สุดก็คือการเตรียมและส่งผ่านผลลัพธ์ไปยังฟังก์ชันอื่น ๆ สิ่งนี้ละเมิดหลักการนี้เช่นกัน หากตัวแปรโกลบอลถูกใช้ในลักษณะนั้น (เช่นตัวแปรโกลบอลที่ใช้ในฟังก์ชัน X จะต้องถูกตั้งค่าในฟังก์ชัน Y ก่อน) หมายความว่าในการทดสอบหน่วยฟังก์ชัน X คุณต้องเรียกใช้ฟังก์ชันทดสอบ / รัน Y ก่อน
ในทางกลับกันและตามที่คนอื่น ๆ ได้กล่าวไปแล้วหากใช้ตัวแปร global เป็นตัวแปร "ค่าคงที่" จะดีกว่าเล็กน้อยเนื่องจากภาษาไม่รองรับค่าคงที่ อย่างไรก็ตามฉันมักชอบทำงานกับคลาสและมี "ค่าคงที่" เป็นสมาชิกคลาสและไม่ใช้ตัวแปรส่วนกลางเลย หากคุณมีรหัสที่สองคลาสที่แตกต่างกันต้องการเพื่อแบ่งปันตัวแปรส่วนกลางคุณอาจต้องปรับโครงสร้างโซลูชันของคุณใหม่และทำให้คลาสของคุณเป็นอิสระ
ฉันไม่เชื่อว่าไม่ควรใช้ globals แต่หากมีการใช้งานผู้เขียนควรพิจารณาหลักการบางประการ (หลักการที่กล่าวถึงข้างต้นอาจรวมถึงหลักการทางวิศวกรรมซอฟต์แวร์และแนวทางปฏิบัติที่ดีอื่น ๆ ) เพื่อรหัสที่สะอาดและเกือบจะปราศจากข้อบกพร่อง
สิ่งเหล่านี้มีความสำคัญหน้าจอเป็นตัวอย่างที่ดี อย่างไรก็ตามในสภาพแวดล้อมแบบมัลติเธรดหรือกับนักพัฒนาหลายคนที่เกี่ยวข้องในทางปฏิบัติมักจะมีคำถามเกิดขึ้น: ใครเป็นคนกำหนดหรือล้างมัน (ผิดพลาด)? ขึ้นอยู่กับสถาปัตยกรรมการวิเคราะห์อาจมีค่าใช้จ่ายสูงและจำเป็นต้องใช้บ่อยครั้ง ในขณะที่การอ่าน global var สามารถใช้ได้ แต่การเขียนถึงจะต้องได้รับการควบคุมเช่นโดย single thread หรือ threadsafe class ดังนั้นตัวแทนทั่วโลกจึงเกิดความกลัวว่าจะมีค่าใช้จ่ายในการพัฒนาที่สูงซึ่งเป็นไปได้จากผลที่ตัวเองถูกมองว่าชั่วร้าย ดังนั้นโดยทั่วไปจึงควรรักษาจำนวนตัวแทนทั่วโลกให้ต่ำ
eval
,import *
, concatenation สตริง , ตัวแปรid
, เงาแอตทริบิวต์ )