2012-01-01 128 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)是我現在用的。

相關問題