2012-12-17 3 views
3

부모 클래스의 메소드를 호출하는 여러 수퍼 클래스가있는 서브 클래스에 문제가 있습니다. __init__이 어떻게 부모의 인스턴스를 필요로하는지에 대해 오류가 발생하지만 자식의 인스턴스가 있습니다. StackOverflow에 대한 다른 질문은 이것이 부모 클래스에서 여러 번 정의 된 것이므로 인터프리터에 입력 된 간단한 스크립트로 확인한 것입니다.파이썬에서 클래스 정의가 여러 번 포함되지 않도록하려면 어떻게해야합니까?

참고 : 이것은 내가 궁금한 내용이 아닙니다. Base 클래스가 다시 정의되고 Inherited 클래스가 더 이상 제대로 작동하지 않게하는 문제를 보여주는 예제입니다.

>>> class Base(object): 
...  def __init__(self): 
...    print "Base!" 
... 
>>> class Inherited(Base): 
...  def __init__(self): 
...    Base.__init__(self) 
...    print "Inherited" 
... 
>>> class Base(object): 
...  def __init__(self): 
...    print "Base!" 
... 
>>> Inherited() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 3, in __init__ 
TypeError: unbound method __init__() must be called with Base instance as first argument (got Inherited instance instead) 
>>> 

제 질문은 기본 클래스가 여러 번 정의되지 않도록하려면 어떻게합니까? 내가 작업하고있는 프로젝트에는 여러 파일과 가져 오기가 있기 때문에 파일을 한 번만 포함 시키려면 모든 것을 리팩토링하는 것이 어려울 것입니다.

+1

동일한 모듈을 여러 번 가져 오기 만하면이 문제가 발생하지 않습니다. 다른 일이 계속되어야합니다. 이게 뭐야? – NPE

+1

같은 전역 네임 스페이스에 Base라는 두 개의 다른 클래스를 만들어이 문제를 만듭니다. 이러지 마. 동일한 동작을 나타내는 모듈로 코드 분할을 표시하십시오. – Marcin

+0

'Base'가 모듈에 정의되어 있다면, 그 모듈을 여러 번 가져 오기만하면 처음으로 정의가 실행되기 때문에 문제가되지 않습니다. 질문에서 샘플 코드는 콘솔에서 정의를 명시 적으로 실행하고 있기 때문에 가짜입니다. 동일한 것은 아닙니다. – martineau

답변

3

이 동작은 나에게 매우 비현실적인 것 같습니다. 동일한 모듈을 다른 방식으로 가져 오면 클래스 (Base)가 동일한 클래스 객체를 참조합니다. 수입을 통해이 상황에 들어갈 가능성은 희박합니다.

그러나, 한 가지 해결 방법은 super을 사용하는 것입니다

class Base(object): 
    def __init__(self): 
      print "Base!" 

class Inherited(Base): 
    def __init__(self): 
      super(Inherited,self).__init__() 
      print "Inherited" 

class Base(object): 
    def __init__(self): 
      print "Base!" 

Inherited() 

super는 당신이 실제로 호출하고 있음을 보장하는 기본 클래스의 __init__보다는에 기본 클래스를 대신하는 일이 다른 클래스 현재 모듈의 네임 스페이스.

+3

OP는 어쨌든'super'를 사용해야합니다. –

+1

@DanielRoseman - 단순한 Google 검색이 나타날 다양한 '최고'기사를 지적하는 것이 가치가 있습니다. [ "super consider harmful"] (https://fuhm.net/super-harmful/) 및 이에 상응하는 [ super consider super "] (http://rhettinger.wordpress.com/2011/05/26/super-considered-super/) – mgilson

+0

super()를 사용하기 위해 전체 코드베이스를 다시 작성하는 것은 현 시점에서는 비현실적입니다. – samoz

3

Inherited 하위 정의 클래스 정의로 Base (정의한 첫 번째 정의)의 원본 정의가 하위 클래스로 분류되므로 하위 클래스가 읽히는대로 처리됩니다.

그러나 런타임에 __init__ 정의 Base의 정의가 사용됩니다. 이 클래스는 자신의 인스턴스를 기대하지만 대신 Base이라는 첫 번째 정의의 인스턴스를받습니다.

이런 식으로 항목을 입력 할 때 인터프리터는 동일한 클래스임을 알 수 없습니다. 그러나 파일에서 가져올 때이 문제는 발생하지 않습니다. Python은 파일을 두 번 가져올 때 클래스가 동일하다는 것을 알기에 충분히 똑똑합니다.

다른 것이 코드로 진행 중이므로 사용 사례에 더 자세히 살펴 보는 것이 도움이 될 것입니다. 여러 모듈에서 같은 이름의 클래스를 정의한 다음 동일한 네임 스페이스로 가져 오는 경우에만 문제가 발생합니다.

+0

이미 정의되어 있는지 확인하는 방법이 있습니까? 내가 말할 수있는 것부터, 코드베이스는 런타임에 많은 수의 가져 오기와 디렉토리를 변경하는 중입니다. 이로 인해 일부 항목을 잘못 다시 가져올 수 있습니다. 또한, 코드 중 일부는 __init__.py 함수 내부에 있으며, 잘못 입력하지 않으면 패키지로 변경됩니다. – samoz

+0

상속 된''__init__'의 처음에'Inherited .__ bases__'과'Base'를 출력 할 수 있습니다. 이것은 'Base'의 두 인스턴스가 정의 된 곳을 보여줍니다. 두 모듈 모두 동일한 모듈 경로를 표시하면 동일한 파일에'Base'가 두 번 정의되어있을 수 있습니다. –

+0

@ samos : 이것은 문제의 정확한 분석 인 것 같습니다. 문제는 범위 지정 규칙입니다. 'Base' 클래스를 파생 클래스에 바인딩해야합니다. 'super() '를 사용하면이 작업을 수행 할 수 있지만 파생 클래스 정의에서 기본 클래스에 대한 명시 적 참조를 포함하고 Base 대신이 값을 사용할 수도 있습니다. 또한 클래스 이름을 가져 오지 않고 모듈 이름으로 모든 클래스를 한정하는 경우 도움이 될 수 있습니다. – Ber

관련 문제