如果第一个参数不是类,则issubclass引发异常

时间:2012-01-01 08:41:31

标签: python

我正在开发一个Python应用程序,我需要多次检查对象是否是数据库模型的子类。

我做了我自己的功能:

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

issubclass引发异常的obj不是一个类,但我希望它只是在obj不是类的情况下返回False。

我想更好地制作另一个功能,而不是使用内置的issubclass

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

但为什么内置的issubclass不是那样的呢?什么原因?我错过了什么吗?


更新

我有模特:

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是正常而不是issubclass。如果{{1}}的第一个参数不是类,那么引发TypeError有什么用?

例如有人问狗:“你是解决这个问题的合适人选吗?”,而不是回答“不”,狗说“我不是男人”。我问了一件事(是子类)而且他没有回答我的问题。

3 个答案:

答案 0 :(得分:1)

请阅读isinstanceissubclass的文档。他们解释了一切。

你的意思是“对象是数据库模型的子类”,对吧?它将是一个类,而不是一个类实例?然后是不是那个issubclass呢?为什么摆弄isinstance? - 克里斯摩根刚刚编辑

答案 1 :(得分: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)就是我现在使用的。

答案 2 :(得分:0)

Isinstance可能会做你想要的。当obj是作为Klass子类的类的实例时,isinstance(obj, Klass)将返回True。 例如:

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

“如果issubclass的第一个参数不是类,那么引发TypeError的用处是什么?”

明确比隐含更好。您将非类传递给了issubclass。这表明你做错了什么。因此,您会收到错误消息。如果您真的想将实例传递给issubclass,则可以捕获该错误:

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

或者,当然,你可以做你做的事情:额外检查。

但是,如果它引发错误,那么就不可能发现传入实例的错误。

根据我的理解,您希望检查API或类似内容,传入的对象是BaseModel的子类,并且不应允许用户传入实例。 IMO,正确的做法是在传递错误的东西时引发TypeError。像这样:

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

在那里设置断言只是意味着你隐藏了传递错误信息的类型错误这一事实。