2011-09-20 70 views
3

我在python中編寫了一些json編碼器,用於字典派生類,類EPPI_dictDB,此類的對象可能會存儲爲值類解析器的一些實例。對象不匹配

但是當我編碼出錯的時候,傳遞給特定編碼器函數的類EPPI_dictDB的實例成爲類解析器的一個實例!

讓我通過一個例子來更好地解釋。 如果我執行這個代碼

import json 
import raw.data_input as data_input 
p = data_input.parser() 
class data(): 
    def __str__(self): 
     return self.name 

data1 = data() 
data1.name = "data1" 
data1.proteins = ['acc1','acc2'] 
data1.peptides = [('acc1',['SEQTWO']), 
         ('acc2',['SEQONE'])] 
p.parse(data1) 
s = EPPI_dbopen('tmp.prj', flag='n') 
s["parser"] = p 

print s.__class__ 
print isinstance(s, EPPI_DictDB) 
print isinstance(s, data_input.parser) 

我得到這些結果:

<class '__main__.EPPI_DictDB'> 
True 
False 

後,我打電話編碼器:

print json.dumps(obj=s, cls=projectEncoder) 

編碼的代碼裏面我把一些「打印」確定通過對象的性質:

class projectEncoder(json.JSONEncoder): 
    def default(self, obj): 

     print obj.__class__ 
     print isinstance(obj, EPPI_DictDB) 
     print isinstance(obj, data_input.parser) 

     if isinstance(obj, EPPI_DictDB): 
      result = obj.__dict__ 
      if "parser" in result.keys(): 
       pars = result["parser"] 
       result["parser"] = parserEncoder().encode(pars) 
      if "selected" in results.keys(): 
       sel = result["selected"] 
       result["selected"] = parserEncoder().encode(sel) 
      return result 
     return json.JSONEncoder.default(self, obj) 

內打印的結果是:

<class 'raw.data_input.parser'> 
False 
True 

任何人都可以解釋我發生什麼事?

回答

0

猜測一下:

JSON編碼器已經知道如何處理類型的字典,所以它把你的字典子類的方式作爲一個字典一樣。但是,當它到達s [「parser」]時,它不知道該如何處理該對象,因此它會調用您的default方法。即從你的代碼,它看到p,而不是s

這似乎是什麼the docs說。在你實際上在做什麼

編輯

看,我覺得應該有實現這個更簡單的方法:

def default(self, obj): 
    if isinstance(obj, data_input.parser): 
     return parserEncoder().encode(obj) 
    return super(projectEncoder, self).default(obj) 

如果"selected"領域是另一種類型,那麼就改變第二行爲:

if isinstance(obj, (data_input.parser, type_of_selected)): 
+0

這個問題不在編碼器類中,而是在內建的'__dict__'中。我做了一個實驗來確定這一點,我編寫了從字典轉換的函數,獲得了我發佈的相同結果。但我明白你的意思,你的信息很清楚,托馬斯K,爲什麼我必須轉換爲字典?這個假設是錯誤的! – gunzapper

+0

@gunzapper:看起來很奇怪。但大概是如果你繼承了字典,你使用了某種映射,並且只有一種方法可以用JSON來表示映射。事實上,看看你在做什麼,應該有一個更簡單的方法來做到這一點。我會編輯我的答案。 –

+0

昨天我選擇了更簡單的方法:在EPPI_DictDB中註冊每個parser對象。我還編寫了getty方法來獲取解析器對象。有用。選擇是解析器的派生類。但是,我認爲這是一種奇怪的行爲。我也會嘗試你的解決方案。 – gunzapper