파이썬에서 같은 파일에 여러 클래스를 두는 것이 괜찮습니까?
예. 철학적 관점과 실제적인 관점에서 모두.
파이썬에서 모듈은 메모리에 한 번 존재하는 네임 스페이스입니다.
파일 당 하나의 클래스가 정의 된 다음과 같은 가상 디렉토리 구조가 있다고 가정하십시오.
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 모듈 소스는 종속성별로 구성됩니다.
- 비 병리학적인 경우, 모듈과 클래스 정의는 모두 메모리에서 한 번 발생하는 싱글 톤입니다. 모듈을 클래스에 양도 적으로 매핑하면 모듈이 중복됩니다.
- 파일 수가 증가하면 클래스를 통해 읽기가 편리하지 않습니다 (단순하게 IDE를 사용하지 않는 한).
이름 공간과 조직적 관점에서 클래스 그룹을 다른 모듈로 나누지 못하게 되었습니까?
아니.
파이썬 의 선에서 , 그것은 성장하고 진화하는 철학과 원칙을 반영합니다.
네임 스페이스는 훌륭한 아이디어 중 하나입니다. 더 많은 것을 해보자!
그러나 다음과 같이 말합니다.
평평한 것이 중첩보다 낫습니다.
파이썬은 매우 깨끗하고 읽기 쉽습니다. 그것은 당신이 그것을 읽을 것을 권장합니다. 모든 개별 수업을 별도의 파일에 넣으면 읽기가 권장되지 않습니다. 이것은 파이썬의 핵심 철학에 위배됩니다. 표준 라이브러리 의 구조를 살펴보십시오. 대다수의 모듈은 패키지가 아닌 단일 파일 모듈입니다. 관용적 인 파이썬 코드는 CPython 표준 라이브러리와 같은 스타일로 작성되었다고 여러분에게 제출하겠습니다.
다음은 추상 기본 클래스 모듈 의 실제 코드입니다 . 언어에서 다양한 추상 유형을 나타내는 데 참조로 사용하고 싶습니다.
이 클래스들 각각에 별도의 파일이 필요하다고 말 하시겠습니까?
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 {}