क्या पायथन में एक ही फ़ाइल में कई कक्षाएं होना ठीक है?
हाँ। दोनों दार्शनिक दृष्टिकोण से और साथ ही व्यावहारिक भी।
पायथन में, मॉड्यूल एक नाम स्थान है जो एक बार स्मृति में मौजूद हैं।
मान लें कि हमारे पास निम्न काल्पनिक निर्देशिका संरचना है, जिसमें प्रति फ़ाइल एक वर्ग परिभाषित है:
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 मॉड्यूल स्रोत निर्भरता द्वारा आयोजित किया जाता है।
- गैर-पैथोलॉजिकल मामलों में, मॉड्यूल और क्लास परिभाषा दोनों एकल हैं, स्मृति में एक बार होने वाली। कक्षाओं में मॉड्यूल की एक विशेषण मानचित्रण होगा - मॉड्यूल को निरर्थक बना देगा।
- फ़ाइलों की बढ़ती संख्या कक्षाओं के माध्यम से आकस्मिक रूप से पढ़ने के लिए कम सुविधाजनक बनाती है (जब तक कि आपके पास आईडीई नहीं है जो इसे सरल बनाता है) - यह बिना उपकरण के लोगों के लिए कम सुलभ बनाता है।
क्या आप अलग-अलग मॉड्यूल में कक्षाओं के समूहों को तोड़ने से रोकते हैं जब आप इसे नाम स्थान और संगठनात्मक दृष्टिकोण से वांछनीय पाते हैं?
नहीं।
पायथन के ज़ेन से , जो उस दर्शन और सिद्धांतों को दर्शाता है जिसके तहत यह विकसित हुआ और विकसित हुआ:
नाम स्थान एक महान विचार का सम्मान कर रहे हैं - चलो उन में से अधिक करते हैं!
लेकिन हम ध्यान रखें कि यह भी कहता है:
फ्लैट नेस्टेड से बेहतर है।
पायथन अविश्वसनीय रूप से स्वच्छ और पढ़ने में आसान है। यह आपको इसे पढ़ने के लिए प्रोत्साहित करता है। हर एक अलग वर्ग को एक अलग फ़ाइल में रखना पढ़ने को हतोत्साहित करता है। यह पायथन के मूल दर्शन के खिलाफ जाता है। स्टैंडर्ड लाइब्रेरी की संरचना को देखें , अधिकांश मॉड्यूल एकल-फ़ाइल मॉड्यूल हैं, न कि पैकेज। मैं आपके सामने प्रस्तुत करूंगा कि मुहावरेदार पायथन कोड उसी शैली में लिखा गया है जैसा कि CPython standard lib है।
यहाँ सार आधार वर्ग मॉड्यूल से वास्तविक कोड है । मैं इसे भाषा में विभिन्न अमूर्त प्रकारों के निरूपण के लिए एक संदर्भ के रूप में उपयोग करना पसंद करता हूं।
क्या आप कहेंगे कि इनमें से प्रत्येक वर्ग को एक अलग फाइल की आवश्यकता होगी?
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
तो क्या वे प्रत्येक की अपनी फ़ाइल होनी चाहिए?
मुझे आशा नहीं है।
ये फाइलें सिर्फ कोड नहीं हैं - वे पायथन के शब्दार्थ पर दस्तावेज हैं।
वे शायद औसतन 10 से 20 लाइनें हैं। कोड की एक और 10 लाइनों को देखने के लिए मुझे पूरी तरह से अलग फ़ाइल पर क्यों जाना चाहिए? यह बहुत अव्यवहारिक होगा। इसके अलावा, कोड की अधिक अनावश्यक लाइनों को जोड़ते हुए, प्रत्येक फ़ाइल पर लगभग समान बॉयलरप्लेट आयात होगा।
मुझे यह जानना काफी उपयोगी है कि एक एकल मॉड्यूल है जहां मैं इन सभी सार बेस कक्षाओं को पा सकता हूं, बजाय इसके कि मॉड्यूल की सूची पर ध्यान दिया जाए। उन्हें एक-दूसरे के संदर्भ में देखने से मुझे उन्हें बेहतर ढंग से समझने में मदद मिलती है। जब मैं देखता हूं कि एक Iterator एक Iterable है, तो मैं जल्दी से समीक्षा कर सकता हूं कि एक Iterable में क्या होता है।
मैं कभी-कभी बहुत कम कक्षाओं के एक जोड़े को हवा देता हूं। वे फ़ाइल में बने रहते हैं, भले ही उन्हें समय के साथ बड़ा होने की आवश्यकता हो। कभी-कभी परिपक्व मॉड्यूल में 1000 से अधिक लाइनें होती हैं। लेकिन ctrl-f आसान है, और कुछ IDE फ़ाइल की रूपरेखा को देखना आसान बनाते हैं - इसलिए फ़ाइल चाहे कितनी भी बड़ी हो, आप जिस भी वस्तु या विधि की तलाश कर रहे हैं, आप जल्दी जा सकते हैं।
निष्कर्ष
मेरी दिशा, पायथन के संदर्भ में, एक ही फाइल में संबंधित और शब्दार्थ समान श्रेणी की परिभाषाएं रखना पसंद करती है। यदि फ़ाइल इतनी बड़ी हो जाती है कि वह बहुत बड़ी हो जाती है, तो एक पुनर्गठन पर विचार करें।
class SomeException extends \Exception {}