โมดูล (และแพ็คเกจ) เป็นวิธีที่ยอดเยี่ยมของ Pythonic ในการแบ่งโปรแกรมของคุณออกเป็นเนมสเปซแยกกันซึ่งดูเหมือนว่าจะเป็นเป้าหมายโดยปริยายของคำถามนี้ อันที่จริงขณะที่ฉันเรียนรู้พื้นฐานของ Python ฉันรู้สึกผิดหวังที่ไม่มีคุณสมบัติขอบเขตบล็อก อย่างไรก็ตามเมื่อฉันเข้าใจโมดูล Python แล้วฉันก็สามารถบรรลุเป้าหมายก่อนหน้านี้ได้อย่างสง่างามมากขึ้นโดยไม่ต้องใช้ขอบเขตการบล็อก
เพื่อเป็นแรงจูงใจและเพื่อชี้ให้ผู้คนไปสู่ทิศทางที่ถูกต้องฉันคิดว่าการให้ตัวอย่างที่ชัดเจนของโครงสร้างขอบเขตของ Python นั้นมีประโยชน์ ก่อนอื่นฉันอธิบายความพยายามที่ล้มเหลวในการใช้คลาส Python เพื่อใช้ขอบเขตบล็อก ต่อไปฉันจะอธิบายว่าฉันบรรลุสิ่งที่มีประโยชน์มากขึ้นโดยใช้โมดูล Python ได้อย่างไร ในตอนท้ายฉันร่างการประยุกต์ใช้แพคเกจในการโหลดและกรองข้อมูล
กำลังพยายามบล็อกขอบเขตกับคลาส
ครู่หนึ่งฉันคิดว่าฉันได้บรรลุขอบเขตการบล็อกโดยการติดรหัสไว้ในการประกาศคลาส:
x = 5
class BlockScopeAttempt:
x = 10
print(x)
print(x)
น่าเสียดายที่สิ่งนี้พังลงเมื่อมีการกำหนดฟังก์ชัน:
x = 5
class BlockScopeAttempt:
x = 10
print(x)
def printx2():
print(x)
printx2()
นั่นเป็นเพราะฟังก์ชันที่กำหนดภายในคลาสใช้ขอบเขตส่วนกลาง วิธีที่ง่ายที่สุด (แต่ไม่ใช่วิธีเดียว) ในการแก้ไขปัญหานี้คือการระบุคลาสอย่างชัดเจน:
x = 5
class BlockScopeAttempt:
x = 10
print(x)
def printx2():
print(BlockScopeAttempt.x)
printx2()
สิ่งนี้ไม่สวยหรูนักเพราะต้องเขียนฟังก์ชันต่างกันขึ้นอยู่กับว่ามีอยู่ในชั้นเรียนหรือไม่
ผลลัพธ์ที่ดีขึ้นด้วยโมดูล Python
โมดูลนั้นคล้ายกับคลาสแบบคงที่มาก แต่โมดูลนั้นสะอาดกว่ามากจากประสบการณ์ของฉัน ในการทำเช่นเดียวกันกับโมดูลฉันสร้างไฟล์ที่เรียกว่าmy_module.py
ในไดเร็กทอรีการทำงานปัจจุบันโดยมีเนื้อหาต่อไปนี้:
x = 10
print(x)
def printx():
global x
print(x)
จากนั้นในไฟล์หลักของฉันหรือเซสชันโต้ตอบ (เช่น Jupyter) ฉันทำ
x = 5
import my_module
my_module.printx()
print(x)
ตามคำอธิบายไฟล์ Python แต่ละไฟล์กำหนดโมดูลที่มีเนมสเปซส่วนกลางของตัวเอง การนำเข้าโมดูลช่วยให้คุณสามารถเข้าถึงตัวแปรในเนมสเปซนี้ด้วย.
ไวยากรณ์
หากคุณกำลังทำงานกับโมดูลในเซสชันแบบโต้ตอบคุณสามารถดำเนินการสองบรรทัดนี้ได้ในตอนต้น
%load_ext autoreload
%autoreload 2
และโมดูลจะโหลดใหม่โดยอัตโนมัติเมื่อไฟล์ที่เกี่ยวข้องถูกแก้ไข
แพ็กเกจสำหรับโหลดและกรองข้อมูล
แนวคิดเรื่องแพ็คเกจเป็นส่วนขยายเล็กน้อยของแนวคิดโมดูล แพ็กเกจคือไดเร็กทอรีที่มีไฟล์ (อาจว่างเปล่า) __init__.py
ซึ่งดำเนินการเมื่อนำเข้า โมดูล / แพ็คเกจภายในไดเร็กทอรีนี้สามารถเข้าถึงได้ด้วย.
ไวยากรณ์
สำหรับการวิเคราะห์ข้อมูลฉันมักจะต้องอ่านไฟล์ข้อมูลขนาดใหญ่จากนั้นจึงใช้ตัวกรองต่างๆแบบโต้ตอบ การอ่านไฟล์ใช้เวลาหลายนาทีดังนั้นฉันจึงต้องการทำเพียงครั้งเดียว จากสิ่งที่ฉันเรียนรู้ในโรงเรียนเกี่ยวกับการเขียนโปรแกรมเชิงวัตถุฉันเคยเชื่อว่าควรเขียนโค้ดสำหรับกรองและโหลดเป็นวิธีการในชั้นเรียน ข้อเสียที่สำคัญของแนวทางนี้คือถ้าฉันกำหนดตัวกรองของฉันใหม่คำจำกัดความของคลาสของฉันจะเปลี่ยนไปดังนั้นฉันจึงต้องโหลดคลาสใหม่ทั้งหมดรวมถึงข้อมูลด้วย
ทุกวันนี้ด้วย Python ฉันกำหนดแพ็คเกจที่เรียกว่าmy_data
ซึ่งมีโมดูลย่อยชื่อload
และfilter
. ภายในของfilter.py
ฉันสามารถนำเข้าสัมพัทธ์:
from .load import raw_data
ถ้าฉันแก้ไขfilter.py
ก็autoreload
จะตรวจพบการเปลี่ยนแปลง มันไม่โหลดซ้ำload.py
ดังนั้นฉันไม่จำเป็นต้องโหลดข้อมูลของฉันใหม่ วิธีนี้ฉันสามารถสร้างต้นแบบรหัสกรองของฉันในโน๊ตบุ๊ค Jupyter filter.py
ห่อเป็นฟังก์ชั่นและจากนั้นตัดวางจากสมุดบันทึกของฉันโดยตรงใน การคิดว่านี่เป็นการปฏิวัติขั้นตอนการทำงานของฉันและทำให้ฉันเปลี่ยนจากคนขี้ระแวงเป็นผู้เชื่อใน“ Zen of Python”
One purpose (of many) is to improve code readability
- รหัส Python ที่เขียนอย่างถูกต้อง (เช่นตามzen ของ python ) ไม่จำเป็นต้องมีการปรุงแต่งเพื่อให้อ่านได้ อันที่จริงมันเป็นหนึ่งในหลาย ๆ สิ่งที่ฉันชอบเกี่ยวกับ Python