2009-03-12 2 views
5

매개 변수로 유형을 가져 오는 파이썬 메소드가 있다고 가정합니다. 주어진 유형이 중첩 된 클래스인지 판단 할 수 있습니까?
예. 이 예에서 :python : 클래스가 중첩되었는지 확인

def show_type_info(t): 
    print t.__name__ 
    # print outer class name (if any) ... 

class SomeClass: 
    pass 

class OuterClass: 
    class InnerClass: 
     pass 

show_type_info(SomeClass) 
show_type_info(OuterClass.InnerClass) 

나는 InnerClass가 OuterClass 내부에 정의되어 있는지 또한 보여 show_type_info(OuterClass.InnerClass)에 전화를하고 싶습니다.

+0

자기 자신이 뭐가 잘못 되었나요? __.__ name__? 이 정보에 대한 귀하의 목적은 무엇입니까? –

+0

@ S.Lott : "자기 자신이 무엇이 잘못 되었습니까?"라는 것은 무엇을 의미합니까 ?__ class __.__ name__ "? 죄송합니다. 귀하의 질문을 이해할 수 없습니다 ... –

+0

@orsogufo : "잘못된 것"- 작동하지 않습니다 - 적절하지 않습니다 - 도움이되지 않습니다 - 고장났습니다 - 무엇을하지 않습니다 당신이 원한다 - 올바른 형식이 아니다 - 자기 자신이 "틀린".__ class __.__ name__? 그걸로 뭔가 잘못 됐어.하지만 네가 싫어하는 것이 뭔지 모르겠다. 명확히하십시오. –

답변

12

AFAIK는 클래스 및 기타 정보가 없으므로 중첩 된 클래스인지 여부를 알 수 없습니다. 그러나 이것을 결정하기 위해 장식자를 사용하는 방법은 see here입니다.

중첩 된 클래스는 단순히 외부 클래스의 특성 인 일반 클래스입니다. 예를 들어, inspect.getmro은 외부 클래스가 아닌 기본 클래스 만 제공합니다.

또한 중첩 된 클래스는 거의 필요하지 않습니다. 나는 그것이 당신이 하나를 사용하려고 유혹을 느끼는 각각의 특별한 경우에 좋은 접근법인지를 강력하게 재검토 할 것입니다.

+0

+1 좋은 조언입니다. –

+0

감사합니다, 당신의 대답을 수락 : 요점은 중첩 클래스가 외부의 속성이라는 사실입니다. P.S : 항상 중첩 클래스에 대한 대안이있을 것이라고 확신하지만 왜 나쁜 아이디어인지는 알 수 없습니다. –

5

내부 클래스는 파이썬에서 특별히 특별한 기능을 제공하지 않습니다. 클래스 객체의 속성 일 뿐이며 정수 또는 문자열 속성과 다릅니다. 귀하의 OuterClass/InnerClass 예제는 정확히으로 다시 작성할 수 있습니다 : 그 바인딩 단지 일반 변수이기 때문에

class OuterClass(): pass 
class InnerClass(): pass 
OuterClass.InnerClass= InnerClass 

InnerClass는, 그것은 다른 클래스 내에서 선언되었는지 여부를 알 수 없습니다. 바운드 메소드를 소유자의 '자아'에 대해 알려주는 마법은 여기에 적용되지 않습니다.

John이 게시 한 링크의 innerclass 데코레이터 마법은 흥미로운 접근이지만 나는 그대로 사용하지 않습니다. 새로운 InnerClass마다 시간을 얻을 수 있도록, 그것은 각각의 외부 객체의 생성 클래스를 캐시하지 않습니다 당신 outerinstance.InnerClass 전화 :

>>> o= OuterClass() 
>>> i= o.InnerClass() 
>>> isinstance(i, o.InnerClass) 
False # huh? 
>>> o.InnerClass is o.InnerClass 
False # oh, whoops... 

또한 방법은 외부 클래스 변수를 만드는 자바 행동을 복제하려고 getattr/setattr로 내부 클래스에서 사용할 수있는 것은 매우 dodgy하고 불필요합니다. (Python적인 방법은 i .__ outer __. attr을 명시 적으로 호출하는 것이기 때문에).

0

직접 설정하지 않으면 클래스가 중첩되었는지 확인하는 방법이 없다고 생각합니다. 어쨌든 파이썬 클래스는 네임 스페이스로 사용할 수 없기 때문에 (또는 최소한 쉽게), 나는 최선의 일은 단순히 다른 파일을 사용하는 것이라고 말하고 싶다.

4

실제로 중첩 된 클래스는 다른 클래스와 다르지 않습니다. 최상위 네임 스페이스 (다른 클래스에 대신 있음) 이외의 다른 클래스에서 정의 된 클래스입니다. "중첩 된"에서 "최상위가 아닌"으로 설명을 수정하면 필요한만큼 충분히 가까이 올 수 있습니다.

예 :

import inspect 

def not_toplevel(cls): 
    m = inspect.getmodule(cls) 
    return not (getattr(m, cls.__name__, []) is cls) 

이 일반적인 경우에 작동하지만 당신이 클래스 이름을 변경하거나 정의 후 조작되는 상황에서하고 싶은 일을하지 않을 수 있습니다. 예 :

class C:    # not_toplevel(C) = False 
    class B: pass # not_toplevel(C.B) = True 

B=C.B    # not_toplevel(B) = True 

D=C     # D is defined at the top, but... 
del C    # not_toplevel(D) = True 

def getclass():  # not_toplevel(getclass()) = True 
    class C: pass 
1

답장을 보내 주셔서 감사합니다.
메타 솔루션을 사용하여 가능한 해결책을 찾았습니다. 나는 진짜 필요 이상으로 장애물에 대해 더 많은 일을했으며 파이썬 3에는 적용되지 않는 방식으로 완성되었습니다.
어쨌든이 솔루션을 공유하고 싶습니다. 여기에 게시하고 있습니다.

#!/usr/bin/env python 
class ScopeInfo(type): # stores scope information 
    __outers={} # outer classes 
    def __init__(cls, name, bases, dict): 
     super(ScopeInfo, cls).__init__(name, bases, dict) 
     ScopeInfo.__outers[cls] = None 
     for v in dict.values(): # iterate objects in the class's dictionary 
      for t in ScopeInfo.__outers: 
       if (v == t): # is the object an already registered type? 
        ScopeInfo.__outers[t] = cls 
        break; 
    def FullyQualifiedName(cls): 
     c = ScopeInfo.__outers[cls] 
     if c is None: 
      return "%s::%s" % (cls.__module__,cls.__name__) 
     else: 
      return "%s.%s" % (c.FullyQualifiedName(),cls.__name__) 

__metaclass__ = ScopeInfo 

class Outer: 
    class Inner: 
     class EvenMoreInner: 
      pass 

print Outer.FullyQualifiedName() 
print Outer.Inner.FullyQualifiedName() 
print Outer.Inner.EvenMoreInner.FullyQualifiedName() 
X = Outer.Inner 
del Outer.Inner 
print X.FullyQualifiedName()