한 클래스가 다른 클래스의 서브 클래스인지 확인하려면 (런타임에) 어떻게 확인합니까?


197

하트, 스페이드, 다이아몬드, 클럽이라는 클래스 슈트와 네 가지 서브 클래스가 있다고 가정 해 봅시다.

class Suit:
   ...
class Heart(Suit):
   ...
class Spade(Suit):
   ...
class Diamond(Suit):
   ...
class Club(Suit):
   ...

인스턴스가 아닌 클래스 객체 인 매개 변수로 양복을받는 메소드가 있습니다. 보다 정확하게는 하트, 스페이드, 다이아몬드, 클럽의 네 가지 값 중 하나만받을 수 있습니다. 그런 것을 보장하는 어설 션을 어떻게 만들 수 있습니까? 다음과 같은 것 :

def my_method(suit):
   assert(suit subclass of Suit)
   ...

파이썬 3을 사용하고 있습니다.


1
@Leopd : 정말 명확하지 않습니까? 나는 my_method매개 변수로 얻을 수 있는 가능한 네 가지 값이 무엇인지 정확히 언급했다 : "네 가지 값 중 하나만받을 수있다 : 하트, 스페이드, 다이아몬드, 클럽". 이러한 값은 클래스 인스턴스가 아니라 클래스 객체입니다. 대답이 두 가지 가능성을 모두 다루기 때문에 모호함에 대해 옳다고 생각하지만 그것은 나에게 분명한 것처럼 보입니다. 명확한 문구가 있다면 질문을 편집 할 수 있습니다. 의견 주셔서 감사합니다.
snakile

@snakile 예, 그것은 분명하지 않습니다. 이 주제에서는 누구나 자기 표현의 정확성에 의존하기 때문에 얇은 얼음입니다. 많은 신규 이민자들은 모든 것을 파이썬으로 얻을 수 없으며, 한 가지를 표현할 수 있지만 다른 것을 생각할 수도 있습니다. 그것은 현실이며 순수성을 제외하고는 이민자들이이 행동을 기대하는 것은 상당히 합리적입니다. 당신의 평판이 당신의 표현이 올바른지, 아니면 "정확성 측면에서"말해야하는지에 대한 유일한 힌트 입니다. 본인은 귀하의 지식을 고려하고자하는 바램을 이해하고 있으며, 계속해서 새롭게 등장하는 새로운 사람들을 고려하지 않는 것은 여전히 ​​비합리적입니다.
n611x007

1
그 @snakile, 그리고 것은 그것과 같은 매개 변수 이름 접미사 명명 규칙 사용하는 것이 합리적 일 수 있다는 _class처럼 그들을 만들기를 suit_class. 나는 그 와 같은 명명 규칙을 관련 질문제안 했다 .
n611x007 12

예제 코드에 네 줄을 추가하는 것이 my_method(Heart) my_method(Spade)
Bob Stein

테스트중인 변수가 클래스임을 보장하지 않는 경우, 클래스 3 이 아닌 경우 전달되면 오류가 발생 하므로 Python 3에서 조건을 추가 inspect.isclass하거나 간단히 사용할 수 있습니다 . 이 답변을 참조하십시오 . 나는 아래의 답변에 대해 언급했을 것이지만, 결코 오늘의 빛을 보지 못했을 것입니다. isinstance(myvar, type)issubclass
totalhack

답변:


225

당신은 사용할 수 있습니다 issubclass()이런 식으로 assert issubclass(suit, Suit).


55
"하지만 왜 그런 일을 하시겠습니까?" -컨테이너 클래스가 균질해야하고 삽입 할 때 유형을 확인하는 유일한 방법은 무엇입니까?
Adam Parkin

140
스택 오버플로에 상수가있는 것이 있다면 isinstance 또는 issubclass를 암시하는 답변이있는 모든 질문에도 오리 타이핑에 대한 강의가 수반됩니다!
벤 로버츠

26
내 numpy dtype이 이미지 처리 응용 프로그램의 float 또는 int인지 감지하는 방법을 찾으려고이 질문을 보았습니다. 플로트 인 경우 컨벤션은 0.0과 1.0 사이에서 정규화하는 것이고, int 인 경우 컨벤션은 0 ~ 255입니다. 나는 이미지를 떨리게하기 위해 모든 종류의 변형을 거칠 수 있지만 훨씬 더 직설적입니다. 그냥 "당신은 오리입니까?"하고 내 작업의 규모를 적절하게 조정하십시오.
Omegaman

28
서브 클래스 테스트는 많은 것들, 특히 장고 모델의 단위 테스트를 훨씬 쉽게 만듭니다. "파이썬은 자바가 아니다." 파이썬 프로그래머는 왜 그런 칩을 어깨에 두어야합니까?
Michael Bacon

20
결국 상상력이없고 오만한 말 때문에 반항하지 않습니다. 왜 그렇게 할 필요가 없는지에 대한 설명은 더 친근하고 도움이 될 것입니다.
Michael Scheper 2016 년


26

isinstance인스턴스가 있거나 issubclass클래스가있는 경우 사용할 수 있습니다 . 일반적으로 나쁜 생각이라고 생각했습니다. 일반적으로 파이썬에서는 객체가 그 일을 시도하여 무언가를 할 수 있는지 알아냅니다.


당신이 그것으로 그 일을 할 수 없다는 것을 알게되면 어떻게됩니까? 당신은 예외를 잡아 다른 것을 시도합니까?
wrongusername

2
@ 잘못된 사용자 이름 : 그것은 'Pythonic'방법입니다. 나는이 관습에 장점이 있다고 생각하므로 코드를 명확하게 유지하는 한 그것을 따르십시오. 여기에 대한 좋은 토론이 있습니다 : stackoverflow.com/questions/7604636/…
Michael Scheper

8
@ Michael Scheper : 나는 그것이 pythonic 방식이라면, pythonic 방식을 정말 싫어합니다. IMO, 예외는 제어 흐름에 사용해서는 안됩니다. 오류가 발생할 수 있다고 생각되면이를 방지하십시오. GOTO처럼 취급하지 마십시오. 당신이 게시 한 재미있는 링크
leviathanbadger

@ aboveyou00 : '내 코드를 명확하게 유지하는 한'위반하는 사례처럼 들립니다. 그러나 많은 사람들이 EAFP 원칙을 남용하고 찾기 어려운 버그를 만들어 내기 때문에 모든 파이썬 관습을 좋아하는 사람은 아닙니다.
Michael Scheper

이 점검은 계약을 정의 할 때 편리합니다. 예를 들어, 객체를받는 생성자 : 우리는 수신 된 객체가 주어진 클래스의 인스턴스라고 주장하고, 그렇게함으로써 생성자에게 기대하는 것을 코드 리더에게 알려줍니다.
mastropi

21

issubclass(sub, sup)주어진 서브 클래스가있는 경우 부울 함수는 true를 반환 sub실제로 슈퍼 클래스의 서브 클래스입니다 sup.


9
잘못된 강의가없는 대답 +1.
Gringo Suave 2016 년

2

issubclass 최소한의 실행 가능한 예

다음은 몇 가지 주장이 포함 된보다 완전한 예입니다.

#!/usr/bin/env python3

class Base:
    pass

class Derived(Base):
    pass

base = Base()
derived = Derived()

# Basic usage.
assert issubclass(Derived, Base)
assert not issubclass(Base, Derived)

# True for same object.
assert issubclass(Base, Base)

# Cannot use object of class.
try:
    issubclass(derived, Base)
except TypeError:
    pass
else:
    assert False

# Do this instead.
assert isinstance(derived, Base)

GitHub 업스트림 .

Python 3.5.2에서 테스트되었습니다.


1

내장 issubclass를 사용할 수 있습니다. 그러나 오리 타이핑을 사용할 수 있기 때문에 유형 검사는 일반적으로 필요하지 않은 것으로 보입니다.


1

issubclass를 사용하는 것은 로그 레벨을 작성하는 깔끔한 방법 인 것 같습니다. 사용하는 것이 이상하다고 생각하지만 다른 옵션보다 깨끗합니다.

class Error(object): pass
class Warn(Error): pass
class Info(Warn): pass
class Debug(Info): pass

class Logger():
    LEVEL = Info

    @staticmethod
    def log(text,level):
        if issubclass(Logger.LEVEL,level):
            print(text)
    @staticmethod
    def debug(text):
        Logger.log(text,Debug)   
    @staticmethod
    def info(text):
        Logger.log(text,Info)
    @staticmethod
    def warn(text):
        Logger.log(text,Warn)
    @staticmethod
    def error(text):
        Logger.log(text,Error)

0

Python doc 에 따르면 class.__mro__속성 또는 class.mro()메소드를 사용할 수도 있습니다 .

class Suit:
    pass
class Heart(Suit):
    pass
class Spade(Suit):
    pass
class Diamond(Suit):
    pass
class Club(Suit):
    pass

>>> Heart.mro()
[<class '__main__.Heart'>, <class '__main__.Suit'>, <class 'object'>]
>>> Heart.__mro__
(<class '__main__.Heart'>, <class '__main__.Suit'>, <class 'object'>)

Suit in Heart.mro()  # True
object in Heart.__mro__  # True
Spade in Heart.mro()  # False

-5
#issubclass(child,parent)

class a:
    pass
class b(a):
    pass
class c(b):
    pass

print(issubclass(c,b))#it returns true

1
코드 전용 답변은 SO에 감사하지 않으므로 항상 설명 텍스트를 코드에 추가해야합니다. 그러나이 답변은 불필요합니다. 이전 답변에서 아직 언급되지 않은 정보는 추가하지 않습니다.
PM 2Ring
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.