มันดีไหมที่จะมีหลายคลาสในไฟล์เดียวกันใน Python?
ใช่. ทั้งจากมุมมองเชิงปรัชญาเช่นเดียวกับในทางปฏิบัติ
ใน Python โมดูลคือเนมสเปซที่มีอยู่ครั้งเดียวในหน่วยความจำ
สมมติว่าเรามีโครงสร้างไดเรกทอรีสมมุติต่อไปนี้โดยกำหนดหนึ่งคลาสต่อไฟล์:
Defines
abc/
|-- callable.py Callable
|-- container.py Container
|-- hashable.py Hashable
|-- iterable.py Iterable
|-- iterator.py Iterator
|-- sized.py Sized
... 19 more
คลาสเหล่านี้ทั้งหมดมีอยู่ในcollections
โมดูลและ (ซึ่งในความเป็นจริงทั้งหมด 25 รวม) ถูกกำหนดในโมดูลไลบรารีมาตรฐานใน_collections_abc.py
มีสองประเด็นที่ฉันเชื่อว่าทำให้_collections_abc.py
ดีกว่าโครงสร้างไดเรกทอรีทางเลือกสมมุติ
- ไฟล์เหล่านี้เรียงตามตัวอักษร คุณสามารถจัดเรียงไฟล์ด้วยวิธีอื่นได้ แต่ฉันไม่ทราบคุณลักษณะที่เรียงลำดับไฟล์ตามการพึ่งพาความหมาย แหล่งโมดูล _collections_abc ถูกจัดระเบียบตามการพึ่งพา
- ในกรณีที่ไม่ใช่ทางพยาธิวิทยาทั้งโมดูลและคำจำกัดความของคลาสเป็นซิงเกิลตันที่เกิดขึ้นหนึ่งครั้งในหน่วยความจำ จะมีการทำแผนที่ bijective ของโมดูลไปยังคลาสทำให้โมดูลซ้ำซ้อน
- จำนวนไฟล์ที่เพิ่มขึ้นทำให้การอ่านคลาสแบบสบาย ๆ น้อยลง (ยกเว้นว่าคุณมี IDE ที่ทำให้มันง่าย) ทำให้ผู้คนสามารถเข้าถึงได้ง่ายขึ้นโดยไม่ต้องใช้เครื่องมือ
คุณถูกป้องกันไม่ให้แบ่งกลุ่มของคลาสเป็นโมดูลที่แตกต่างกันเมื่อคุณพบว่าเป็นที่ต้องการจากเนมสเปซและมุมมององค์กร
เลขที่
จากZen of Pythonซึ่งสะท้อนถึงปรัชญาและหลักการที่เติบโตและมีวิวัฒนาการ:
Namespaces เป็นหนึ่งในแนวคิดที่ยอดเยี่ยม - ลองทำสิ่งเหล่านี้ให้มากขึ้น!
แต่ให้เราจำไว้ว่ามันยังบอกว่า:
แบนดีกว่าซ้อนกัน
Python สะอาดและอ่านง่าย มันสนับสนุนให้คุณอ่าน การวางทุกคลาสแยกจากกันในไฟล์แยกกันจะทำให้หมดกำลังใจในการอ่าน สิ่งนี้ขัดกับปรัชญาหลักของ Python ดูโครงสร้างของStandard Libraryโมดูลส่วนใหญ่เป็นโมดูลไฟล์เดียวไม่ใช่แพ็คเกจ ฉันจะส่งให้คุณว่ารหัสงูสำนวนที่เขียนในลักษณะเดียวกับ lib มาตรฐาน CPython
นี่คือรหัสที่เกิดขึ้นจริงจากโมดูลชั้นฐานนามธรรม ฉันชอบที่จะใช้มันเป็นข้อมูลอ้างอิงสำหรับ denotation ของประเภทนามธรรมต่างๆในภาษา
คุณจะบอกว่าแต่ละชั้นเรียนเหล่านี้ควรจะต้องมีไฟล์แยกต่างหาก
class Hashable:
__metaclass__ = ABCMeta
@abstractmethod
def __hash__(self):
return 0
@classmethod
def __subclasshook__(cls, C):
if cls is Hashable:
try:
for B in C.__mro__:
if "__hash__" in B.__dict__:
if B.__dict__["__hash__"]:
return True
break
except AttributeError:
# Old-style class
if getattr(C, "__hash__", None):
return True
return NotImplemented
class Iterable:
__metaclass__ = ABCMeta
@abstractmethod
def __iter__(self):
while False:
yield None
@classmethod
def __subclasshook__(cls, C):
if cls is Iterable:
if _hasattr(C, "__iter__"):
return True
return NotImplemented
Iterable.register(str)
class Iterator(Iterable):
@abstractmethod
def next(self):
'Return the next item from the iterator. When exhausted, raise StopIteration'
raise StopIteration
def __iter__(self):
return self
@classmethod
def __subclasshook__(cls, C):
if cls is Iterator:
if _hasattr(C, "next") and _hasattr(C, "__iter__"):
return True
return NotImplemented
class Sized:
__metaclass__ = ABCMeta
@abstractmethod
def __len__(self):
return 0
@classmethod
def __subclasshook__(cls, C):
if cls is Sized:
if _hasattr(C, "__len__"):
return True
return NotImplemented
class Container:
__metaclass__ = ABCMeta
@abstractmethod
def __contains__(self, x):
return False
@classmethod
def __subclasshook__(cls, C):
if cls is Container:
if _hasattr(C, "__contains__"):
return True
return NotImplemented
class Callable:
__metaclass__ = ABCMeta
@abstractmethod
def __call__(self, *args, **kwds):
return False
@classmethod
def __subclasshook__(cls, C):
if cls is Callable:
if _hasattr(C, "__call__"):
return True
return NotImplemented
ดังนั้นพวกเขาแต่ละคนควรมีไฟล์ของตัวเอง?
ฉันหวังว่าไม่
ไฟล์เหล่านี้ไม่ได้เป็นเพียงรหัส แต่เป็นเอกสารเกี่ยวกับความหมายของ Python
พวกเขาอาจเฉลี่ย 10 ถึง 20 บรรทัด ทำไมฉันต้องไปที่ไฟล์แยกกันโดยสมบูรณ์เพื่อดูโค้ดอีก 10 บรรทัด? ที่จะทำไม่ได้อย่างมาก นอกจากนี้จะมีการนำเข้าแผ่นสำเร็จรูปเกือบเหมือนกันในแต่ละไฟล์เพิ่มรหัสซ้ำซ้อนมากขึ้น
ฉันพบว่ามันค่อนข้างมีประโยชน์ที่จะรู้ว่ามีโมดูลเดียวที่ฉันสามารถค้นหา Abstract Base Classes ทั้งหมดแทนที่จะต้องดูรายการของโมดูล การดูพวกเขาในบริบทซึ่งกันและกันทำให้ฉันเข้าใจพวกเขาดีขึ้น เมื่อฉันเห็นว่า Iterator เป็น Iterable ฉันสามารถตรวจสอบสิ่งที่ Iterable ประกอบด้วยได้อย่างรวดเร็ว
บางครั้งฉันก็จบด้วยการเรียนสั้น ๆ สองสามครั้ง พวกเขาอยู่ในไฟล์แม้ว่าพวกเขาต้องการที่จะเติบโตขนาดใหญ่ในช่วงเวลา บางครั้งโมดูลที่โตแล้วมีโค้ดมากกว่า 1,000 บรรทัด แต่ ctrl-f นั้นง่ายและ IDE บางตัวทำให้ง่ายต่อการดูโครงร่างของไฟล์ - ดังนั้นไม่ว่าไฟล์จะมีขนาดใหญ่แค่ไหนคุณก็สามารถไปที่วัตถุหรือวิธีการใดก็ได้ที่คุณต้องการ
ข้อสรุป
ทิศทางของฉันในบริบทของ Python คือต้องการให้คำจำกัดความของคลาสที่เกี่ยวข้องและมีความหมายคล้ายกันในไฟล์เดียวกัน หากไฟล์มีขนาดใหญ่ขึ้นเรื่อย ๆ ให้ดูเทอะทะให้พิจารณาจัดโครงสร้างใหม่
class SomeException extends \Exception {}