문제

유형을 매개 변수로 가져 오는 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)

전화를 원합니다 show_type_info(OuterClass.InnerClass) 또한 내부 클래스는 외부 외부 내부에 정의되어 있음을 보여줍니다.

도움이 되었습니까?

해결책

Afaik, 수업과 다른 정보가 주어지면 중첩 된 수업인지 아닌지 알 수 없습니다. 하지만, 여기를 봐 데코레이터를 사용하여이를 결정하는 방법.

문제는 중첩 클래스가 단순히 외부 클래스의 속성 인 일반 클래스라는 것입니다. 당신이 예상 할 수있는 다른 솔루션은 아마 그렇지 않을 것입니다. inspect.getmro, 예를 들어, 외부 클래스가 아닌 기본 클래스 만 제공합니다.

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

다른 팁

내부 클래스는 파이썬에서 특별한 특수 기능을 제공하지 않습니다. 정수 나 문자열 속성과 다르지 않은 클래스 객체의 속성 일뿐입니다. 외부 클래스/내부 등급 예제는 다음과 같이 정확하게 다시 작성할 수 있습니다.

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

Innerclass는 다른 클래스 내에서 선언되었는지 여부를 알 수 없습니다. 왜냐하면 그것은 단지 평범한 가변 바인딩이기 때문입니다. 바운드 방법을 주인 '자기'에 대해 알리는 마법은 여기에 적용되지 않습니다.

John이 게시 한 링크의 Innerclass Decorator Magic은 흥미로운 접근 방식이지만 나는 그것을 사용하지 않을 것입니다. 각 외부 객체에 대해 생성하는 클래스를 캐시하지 않으므로 Outerinstance.innerclass를 호출 할 때마다 새 내부를 얻을 수 있습니다.

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

또한 getAttr/setattr을 사용하여 내부 클래스에서 외부 클래스 변수를 이용할 수 있도록하는 Java 동작을 복제하는 방식은 매우 끔찍하며 실제로 불필요합니다 (더 많은 pythonic 방법은 i .__ 외부 __. attr art를 명시 적으로 부르는 것입니다).

실제로 중첩 된 클래스는 다른 클래스와 다르지 않습니다. 단지 최상위 네임 스페이스 (다른 클래스 내부) 외에 다른 곳에서 정의됩니다. 설명을 "중첩"에서 "비 탑 레벨"으로 수정하면 필요한 것에 충분히 가까워 질 수 있습니다.

예 :

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

답변 해 주셔서 감사합니다.
메타 클라스를 사용 하여이 가능한 솔루션을 발견했습니다. 나는 실제 필요보다 장애를 위해 더 많은 일을했으며, Python 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()

당신이 직접 설정하지 않으면, 나는 수업이 중첩되어 있는지 판단 할 방법이 있다고 생각하지 않습니다. 어쨌든 파이썬 클래스는 네임 스페이스로 사용할 수 없거나 최소한 쉽지 않기 때문에 가장 좋은 방법은 단순히 다른 파일을 사용하는 것입니다.

Python 3.3부터 새로운 속성이 있습니다 __qualname__, 클래스 이름뿐만 아니라 외부 클래스의 이름도 제공합니다.

샘플에서 이것은 다음과 같습니다.

assert SomeClass.__qualname__ == 'SomeClass'
assert OuterClass.InnerClass.__qualname__ == 'OuterClass.InnerClass'

만약에 __qualname__ 수업의 '는' '가 포함되어 있지 않습니다. 외부 클래스입니다!

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top