2011-02-06 2 views
112

Предположим, что у меня есть классный костюм и четыре подкласса костюма: Heart, Spade, Diamond, Club.Как проверить (во время выполнения), если один класс является подклассом другого?

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

У меня есть метод, который получает костюм в качестве параметра, который является объектом класса, а не экземпляром. Точнее, он может получить только одно из четырех значений: Heart, Spade, Diamond, Club. Как я могу сделать утверждение, которое обеспечивает такую ​​вещь? Что-то вроде:

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

Я использую Python 3.

+5

Вопрос остается неясным suit', является ли 'является экземпляром костюма подкласса, или если это объект класса. Ответы ниже охватывают обе возможности. – Leopd

+0

@ Leopd: Это действительно непонятно? Я точно сказал, какие возможные четыре значения, которые 'my_method' может получить как параметры:« он может получить только одно из четырех значений: «Сердце, лопата, алмаз, клуб». Эти значения являются объектами класса, а не экземплярами класса. Мне кажется довольно понятным, хотя я полагаю, что вы правы в отношении неопределенности, потому что ответы охватывают обе возможности. Вы более чем можете отредактировать вопрос, если у вас есть более четкое слово для этого. Спасибо за комментарий. – snakile

+0

@snakile да неясно. Из-за того, что на основе правильности чьего-то выражения выражается тонкий лед в этой теме. Многие новички не могут получить вещь все-есть-объект-в-питоне, могут выразить одно, а подумать другое. Это реальность и, в стороне от чистоты, вполне разумно ожидать такого поведения от новичков. Оставляя свою репутацию, указывается только на прямой * намек *, верно ли ваше выражение здесь, или я должен сказать «с точки зрения правильности». Я понимаю желание учитывать ваши знания, и все же иррационально не принимать во внимание постоянно обновляющихся новичков. – n611x007

ответ

126

Вы можете использовать issubclass() как этот assert issubclass(suit, Suit).

Но зачем вы хотите это делать? Python - это не Java.

+0

Вы изменили мой ответ с isinstance на issubclass. Вы действительно проходите классы, а не объекты? –

+1

Да. Каждый костюм представляет собой класс, подкласс Suit. Я хочу здесь четыре возможных значения. Нет экземпляров Костюма, и нет примеров Сердца, Спайда, Клуба или Алмаза. Они одиночные. Это плохой дизайн? – snakile

+42

«Но зачем вам это делать?» - потому что у вас есть класс контейнера, который вам нужно обеспечить, является однородным, и единственный способ сделать это - проверить тип при вставке? –

21

Вы можете использовать isinstance, если у вас есть экземпляр, или issubclass, если у вас есть класс. Обычно думал, что это плохая идея. Обычно в Python вы работаете, если объект способен на что-то, пытаясь сделать с ним эту вещь.

+0

Что делать, если вы узнаете, что с этим не можете справиться? Вы поймаете исключение и попробуйте что-то еще? – wrongusername

+2

@wrongusername: T да, это путинский путь. Я думаю, что этот обычай имеет свои достоинства, поэтому я следую ему, пока он сохраняет мой код в явном виде. Здесь есть хорошая дискуссия: http://stackoverflow.com/questions/7604636/better-to-try-something-and-catch-the-exception-or-test-if-its-possible-first –

+1

@Michael Scheper: Я должен сказать, если это питонический путь, то я действительно ненавижу питоновский путь. IMO, исключения не должны использоваться для управления потоком. Если вы считаете, что может произойти ошибка, защититесь от этого ... не рассматривайте его как GOTO. Интересная ссылка, которую вы опубликовали, хотя – aboveyou00

2

Вы можете использовать встроенный issubclass. Но проверка типа обычно рассматривается как ненужная, потому что вы можете использовать утиную печать.

13

Булева функция возвращает true, если данный подкласс sub действительно является подклассом суперкласса sup.

+4

Ответ без ошибочной лекции +1. –

1

Использование issubclass показало, что это чистый способ записи loglevels. Это выглядит странно, используя его ... но он кажется более чистым, чем другие варианты.

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) 
-5
#issubclass(child,parent) 

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

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

Кодовые ответы не оценены на SO, вы всегда должны добавить в код пояснительный текст.Однако этот ответ лишний: он не добавляет информации, которая еще не упоминалась в предыдущих ответах. –