나는 나의 거대한 수업을 두 개로 나누려고 노력하고있다. 글쎄, 기본적으로 “메인”클래스에 추가하고 다음과 같이 추가 기능과 혼합합니다.
main.py
파일:
import mymixin.py
class Main(object, MyMixin):
def func1(self, xxx):
...
mymixin.py
파일:
class MyMixin(object):
def func2(self: Main, xxx): # <--- note the type hint
...
이제 잘 작동하지만 유형 힌트 MyMixin.func2
는 물론 작동하지 않습니다. 나는 main.py
주기적으로 가져 오기를 얻고 힌트가 없으면 내 편집기 (PyCharm)가 무엇인지 알 수 없기 때문에 가져올 수 없습니다 self
.
저는 Python 3.4를 사용하고 있으며 거기에 솔루션이 있으면 3.5로 이동할 의향이 있습니다.
내 클래스를 두 개의 파일로 분할하고 모든 “연결”을 유지하여 내 IDE가 여전히 자동 완성 및 유형을 알고있는 다른 모든 기능을 제공 할 수있는 방법이 있습니까?
답변
일반적으로 가져 오기주기를 처리하는 매우 우아한 방법은 없습니다. 두렵습니다. 선택 사항은 순환 종속성을 제거하기 위해 코드를 다시 설계하거나 실행 가능하지 않은 경우 다음과 같이하는 것입니다.
# some_file.py
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from main import Main
class MyObject(object):
def func2(self, some_param: 'Main'):
...
TYPE_CHECKING
상수는 항상False
가져 오기가 평가되지 않지만 mypy (및 기타 유형 검사 도구) 그 블록의 내용을 평가할 수 있도록 런타임에.
또한 Main
타입 어노테이션을 문자열로 만들어 효과적으로 포워드 선언해야합니다.Main
런타임에 심볼을 사용할 수 없기 합니다.
Python 3.7 이상을 사용하는 경우 PEP 563 을 활용하여 명시적인 문자열 주석을 제공하지 않아도됩니다 .
# some_file.py
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from main import Main
class MyObject(object):
# Hooray, cleaner annotations!
def func2(self, some_param: Main):
...
from __future__ import annotations
가져 오기 것 모두를 문자열이어야 타입 힌트를하고 평가를 건너 뜁니다. 이것은 우리의 코드를 좀 더 인체 공학적으로 만드는 데 도움이 될 수 있습니다.
즉, mypy와 함께 mixin을 사용하면 현재보다 약간 더 많은 구조가 필요할 수 있습니다. Mypy 는 기본적으로 설명 하는 접근 방식 을 권장합니다. 즉 , 클래스 와 클래스 deceze
모두 상속 하는 ABC를 만드는 것 입니다. Pycharm의 검사기를 행복하게 만들기 위해 비슷한 작업을해야한다면 놀라지 않을 것입니다.Main
MyMixin
답변
유형 검사를 위해서만 클래스를 가져올 때 주기적 가져 오기로 어려움을 겪는 사람들을 위해 : 앞으로 참조 (PEP 484-유형 힌트) 를 사용하는 것이 좋습니다 .
형식 힌트에 아직 정의되지 않은 이름이 포함 된 경우 해당 정의는 나중에 해결 될 문자열 리터럴로 표현 될 수 있습니다.
그래서 대신 :
class Tree:
def __init__(self, left: Tree, right: Tree):
self.left = left
self.right = right
당신은 :
class Tree:
def __init__(self, left: 'Tree', right: 'Tree'):
self.left = left
self.right = right
답변
더 큰 문제는 당신의 유형이 처음부터 정상적이지 않다는 것입니다. MyMixin
혼합 될 것이라고 하드 코딩 된 가정을합니다.Main
반면, 다른 클래스와 혼합 될 수있는 반면,이 경우에는 아마도 깨질 것입니다. 믹스 인이 하나의 특정 클래스로 혼합되도록 하드 코딩 된 경우 메서드를 분리하는 대신 해당 클래스에 직접 작성하는 것이 좋습니다.
건전한 타이핑으로이 작업을 제대로 수행하려면 인터페이스 또는 Python 용어로 추상 클래스에 MyMixin
대해 코딩해야합니다 .
import abc
class MixinDependencyInterface(abc.ABC):
@abc.abstractmethod
def foo(self):
pass
class MyMixin:
def func2(self: MixinDependencyInterface, xxx):
self.foo() # ← mixin only depends on the interface
class Main(MixinDependencyInterface, MyMixin):
def foo(self):
print('bar')
답변
내 원래 시도도 솔루션에 매우 가깝다는 것이 밝혀졌습니다. 이것은 내가 현재 사용하고있는 것입니다.
# main.py
import mymixin.py
class Main(object, MyMixin):
def func1(self, xxx):
...
# mymixin.py
if False:
from main import Main
class MyMixin(object):
def func2(self: 'Main', xxx): # <--- note the type hint
...
가져 if False
오지 않는 import within 문 (그러나 IDE는 어쨌든 그것에 대해 알고 있음)과 Main
런타임에 알려지지 않았기 때문에 클래스를 문자열로 사용합니다 .
답변
완벽한 방법은 파일 (예 :)의 모든 클래스와 종속성을 가져온 __init__.py
다음 from __init__ import *
다른 모든 파일을 가져 오는 것 입니다.
이 경우 당신은
- 해당 파일 및 클래스에 대한 여러 참조를 피하고
- 또한 다른 파일 각각에 한 줄만 추가하면됩니다.
- 세 번째는 사용할 수있는 모든 클래스에 대해 알고있는 pycharm입니다.