Python'da aynı dosyada birden fazla sınıf olması uygun mudur?
Evet. Hem felsefi açıdan hem de pratik bir bakış açısından.
Python'da modüller, bellekte bir kez var olan bir ad alanıdır.
Dosya başına bir sınıf tanımlanmış olan aşağıdaki varsayımsal dizin yapısına sahip olduğumuzu varsayalım:
Defines
abc/
|-- callable.py Callable
|-- container.py Container
|-- hashable.py Hashable
|-- iterable.py Iterable
|-- iterator.py Iterator
|-- sized.py Sized
... 19 more
Bu sınıfların tümü collections
modülde mevcuttur ve standart kütüphane modülünde (aslında toplam 25 adet) tanımlanmıştır._collections_abc.py
Burada _collections_abc.py
alternatif varsayımsal dizin yapısından daha üstün olduğunu düşündüğüm birkaç konu var .
- Bu dosyalar alfabetik olarak sıralanmıştır. Bunları başka şekillerde sıralayabilirsiniz, ancak dosyaları semantik bağımlılıklara göre sıralayan bir özelliğin farkında değilim. _Collections_abc modül kaynağı bağımlılığa göre düzenlenir.
- Patolojik olmayan durumlarda, hem modüller hem de sınıf tanımları, her biri bellekte bir kez meydana gelen singletonlardır. Modüllerin sınıflar üzerinde iki yönlü bir eşlemesi olacaktır - modülleri gereksiz kılar.
- Artan dosya sayısı, sınıfları rahatça okumayı daha kolay hale getirir (basitleştiren bir IDE'niz yoksa) - araçsız insanlar için daha az erişilebilir hale getirir.
Bir ad alanı ve organizasyonel perspektiften istenen bulduğunuzda sınıf gruplarını farklı modüllere ayırmanız engelleniyor mu?
Hayır.
Gönderen Python Zen felsefesi ve onu büyüdü ve gelişti altında prensiplerini yansıtmaktadır:
İsim alanları harika bir fikirdir - hadi bunlardan daha fazlasını yapalım!
Ancak şunu da hatırlatırız:
Düz iç içe geçmişten daha iyidir.
Python inanılmaz temiz ve okunması kolay. Sizi okumanızı teşvik eder. Her ayrı sınıfı ayrı bir dosyaya koymak okumayı engeller. Bu Python'un temel felsefesine aykırıdır. Standart Kütüphanenin yapısına bakın, modüllerin büyük çoğunluğu paketler değil tek dosya modülleridir. Deyimsel Python kodunun CPython standart lib'iyle aynı tarzda yazıldığını size bildiririm.
İşte soyut temel sınıf modülünden gerçek kod . Dilde çeşitli soyut türlerin ifadesi için bir referans olarak kullanmayı seviyorum.
Bu sınıfların her birinin ayrı bir dosya gerektirdiğini söyleyebilir misiniz?
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
Her birinin kendi dosyası olmalı mı?
Umarım değildir.
Bu dosyalar sadece kod değildir, aynı zamanda Python'un semantiği ile ilgili belgelerdir.
Belki ortalama 10 ila 20 hattır. Başka bir 10 satır kod görmek için neden tamamen ayrı bir dosyaya gitmem gerekiyor? Bu çok pratik değildir. Ayrıca, her dosyada neredeyse aynı kazan plakası ithalatı olacak ve daha fazla kod satırı ekleyecektir.
Bir modül listesine bakmak yerine, tüm bu Soyut Temel Sınıfları bulabileceğim tek bir modül olduğunu bilmek oldukça yararlı buluyorum. Onları birbirleriyle bağlam içinde görmek onları daha iyi anlamama izin verir. Bir Yinelemenin Yinelenebilir Bir Olduğunu Gördüğümde , Bir Yinelemenin Neler Olduğunu Gözden Geçirerek Hızlıca Gözden Geçirebilirim.
Bazen birkaç kısa derse giriyorum. Zaman içinde büyümeleri gerekse bile dosyada kalırlar. Bazen olgun modüller 1000'den fazla kod satırına sahiptir. Ancak ctrl-f kolaydır ve bazı IDE'ler dosyanın anahatlarını görüntülemeyi kolaylaştırır - bu nedenle dosya ne kadar büyük olursa olsun, aradığınız nesneye veya yönteme hızla gidebilirsiniz.
Sonuç
Yönüm, Python bağlamında, ilgili ve anlamsal olarak benzer sınıf tanımlarını aynı dosyada tutmayı tercih etmektir. Dosya kullanışsız olacak kadar büyürse, yeniden düzenlemeyi düşünün.
class SomeException extends \Exception {}