2012-01-01 137 views
4

我正在开发一个Python应用程序,我需要多次检查一个对象是否是DB模型的子类。如果第一个参数不是类,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。如果issubclass的第一个参数不是类,那么引发TypeError有什么用处?

例如,有人问一只狗:'你是否是正确的人来解决这个任务?',而不是回答'不',狗说'我不是男人'。我问某人一件事(是子类),他没有回答我的问题。

+0

引发'TypeError'对我来说似乎是一件非常自然的事......它鼓励正确地做事。你试图给'issubclass'坏数据;就像'float('foo')'会引发一个ValueError而不是像在某些语言中那样返回'float'('nan')',这只是Python的做事方式。如果你使用的是静态类型的语言,它通常会在编译时窒息。 – 2012-01-01 09:32:47

回答

0

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

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

“?什么是养类型错误,如果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') 

制作断言那里只是意味着你隐藏的事实,这是一种错误的错误的东西通过。

+0

抱歉,这不是我问的。我的代码在问题中工作。只是想知道为什么'issubclass'在第一个参数是一个类实例时引发异常,迫使我做额外的检查'isinstance(obj,type)' – warvariuc 2012-01-01 09:27:10

+0

我不认为这就是他想要实现的;我认为他只是想改变行为,而不是引发TypeError,而是返回False。如果是这样的话,@warvariuc,我会建议你*不要*这样做,因为它鼓励潦草的编码。你应该知道*如果你正在处理这个类或一个实例,除非你能提供一个很好的理由。 – 2012-01-01 09:29:16

+0

我用示例更新了我的问题 – warvariuc 2012-01-01 10:44:14

1

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

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

+0

>你的意思是“一个对象是一个数据库模型的子类”,对吧? warvariuc 2012-01-01 08:58:31

+0

一个相关的问题:http://stackoverflow.com/questions/5658576/is-there-something-like-pythons-issubclass-which-will-return-false-if-the-first – warvariuc 2012-01-01 09:00:11

+0

是的。但你所说的话一点都不清楚。它仍然不是,如果那不是你的意思(虽然我*想*我得到你想要问的东西)。你能不能更新你的问题,清楚你想要达到的目标? – 2012-01-01 09:26:36

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)是我现在用的。

相关问题