2012-01-01 1 views
4

Я разрабатываю приложение Python, где мне нужно много раз, чтобы проверить, является ли объект подклассом модели БД.issubclass вызывает исключение, если первый аргумент не является классом

Я сделал свою собственную функцию, чтобы сделать это:

def isModel(obj): 
    return isinstance(obj, type) and issubclass(obj, Model) 

issubclass вызывает исключение из OBJ не класс, но я хотел бы она просто возвращает значение False, если obj не является классом.

Я думал, что лучше сделать еще одну функцию, чтобы использовать вместо встроенного issubclass:

def _issubclass(obj, Klass): 
    return isinstance(obj, type) and issubclass(obj, Klass) 

Но почему встроенный issubclass не было сделано, как это? В чем причина? Я что-то упускаю?


UPDATE:

У меня есть модели:

class BaseModel(object): 
    id = Field(...) 

class MyModel(BaseModel): 
    deleted = Field(...) 

В функции я хочу проверить, если аргумент является BaseModel:

def update_model(model): 
    assert isinstance(model, type) and issubclass(model, BaseModel), 'Must be a model' 

issubclass отвечает на вопрос если объект является подклассом данного класса. Если объект является экземпляром класса, поэтому ответ IMO должен быть «Нет, ваш объект не является подклассом BaseModel, потому что он не является классом вообще».

В Python вполне нормально, а не if something is not None or len(something) != 0 использовать if something и не поднимать TypeError. Какова полезность повышения TypeError, если первый аргумент issubclass не является классом?

Например, кто-то спрашивает собаку: «Вы правы, чтобы решить эту задачу?», И вместо того, чтобы отвечать «Нет», собака говорит: «Я не мужчина». Я спросил кого-то одно (это подкласс), и он не ответил на мой вопрос.

+0

Поднятие 'TypeError' кажется мне совершенно естественным делом ... оно поощряет правильное выполнение вещей. Вы пытаетесь дать плохие данные 'issubclass'; так же как 'float ('foo')' будет поднимать значение ValueError, а не возвращать 'float ('nan')', как это было бы на некоторых языках, это просто способ Python делать вещи. Если вы работаете на статически типизированном языке, он обычно задыхается во время компиляции. –

ответ

0

Isinstance, вероятно, сделает то, что вы хотите. isinstance(obj, Klass) вернет True, когда obj является экземпляром класса, который является подклассом Klass. Пример:

>>> class A(object): 
... pass 
... 
>>> class B(A): 
... pass 
... 
>>> obj = B() 
>>> 
>>> isinstance(obj, A) 
True 

«? Что полезность повышения TypeError, если первый аргумент issubclass не является классом»

Явный лучше, чем неявный. Вы передали не-класс в issubclass. Это означает, что вы делаете что-то неправильно. Поэтому вы получаете сообщение об ошибке.Если вы серьезно хотите, чтобы передать экземпляры в issubclass, вы можете поймать эту ошибку:

try: 
    isbasemodel = False 
    if issubclass(x, BaseModel): 
     isbasemodel = True 
except TypeError: 
    # Accept that we test non-classes: 
    pass 

Или, конечно, вы можете делать то, что вы делаете: дополнительную проверку.

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

Из того, что я понимаю, вы хотите сделать проверку API или тому подобное, что переданный объект является подклассом BaseModel, и пользователю не разрешается проходить в экземпляре. ИМО, правильная вещь, которую нужно сделать, - это поднять TypeError, если они пройдут неправильно. Как так:

def update_model(model): 
    if not issubclass(model, BaseModel): 
     raise TypeError('Must be a model') 

Создание Assert там просто означает, что вы скрыть тот факт, что это ошибка типа, чтобы передать в неправильные вещи.

+0

извините, это не то, что я спросил. мой код работает как в вопросе. просто интересно, почему 'issubclass' вызывает исключение, когда его первый аргумент является экземпляром класса, заставляя меня выполнять дополнительную проверку' isinstance (obj, type) ' – warvariuc

+0

Я не думаю, что это то, чего он пытается достичь; Я думаю, что он только хочет изменить поведение, так что вместо того, чтобы поднимать TypeError, он возвращает False. Если это так, @warvariuc, я бы рекомендовал вам не делать этого, поскольку он поощряет неаккуратное кодирование. Вы должны * знать *, если вы имеете дело с классом или экземпляром, если только вы не можете указать, почему нет. –

+0

Я обновил свой вопрос с примера – warvariuc

1

Просьба ознакомиться с документами для isinstance и issubclass. Они все объясняют.

Вы имеете в виду, что «объект является подклассом модели БД», правильно? Что это будет класс, а не экземпляр класса? Тогда разве это не то, что делает issubclass? Почему возиться с вещью? - Крис Морган только что отредактировал

+0

> Вы имеете в виду, что «объект является подклассом модели БД», правильно? warvariuc

+0

Связанный с этим вопрос: http://stackoverflow.com/questions/5658576/is-there-something-like-pythons-issubclass-which-will-return-false-if-the-first – warvariuc

+0

Да. Но то, что вы говорили, было совершенно не понятно. Это все еще не так, если это не то, что вы имели в виду (хотя я думаю, что получаю то, что вы пытаетесь спросить). Не могли бы вы обновить свой вопрос, чтобы быть предельно ясным о том, чего вы хотите достичь? –

1

я нашел более удобный способ, используя метаклассами (как мои модели в любом случае использовать их):

Python 2.7.2+ (default, Oct 4 2011, 20:06:09) 
[GCC 4.6.1] on linux2 

>>> class ModelMeta(type): 
...  "Metaclass for models" 
... 
>>> class Model(object): 
...  "DB model" 
...  __metaclass__ = ModelMeta 
... 
>>> class MyModel(Model): 
...  "A real model" 
... 
>>> isinstance(MyModel, type) and issubclass(MyModel, Model) 
True 
>>> myModelInstance = Model() 
>>> issubclass(MyModel, Model) 
True 
>>> issubclass(myModelInstance, Model) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: issubclass() arg 1 must be a class 
>>> isinstance(MyModel, type) and issubclass(MyModel, Model) 
True 
>>> isinstance(myModelInstance, type) and issubclass(myModelInstance, Model) 
False 
>>> isinstance(MyModel, ModelMeta) 
True 
>>> isinstance(myModelInstance, ModelMeta) 
False 
>>> 

Итак, isinstance(MyModel, ModelMeta) что я использую сейчас.

Смежные вопросы