2012-05-30 80 views
3

我的工作,需要給予它的__dict__屬性通過__init__注入這樣的類:變化__slots__動態

class Torrent(Model): 
    def __init__(self, d): 
     super(Torrent, self).__init__('torrents') 
     self.__dict__ = d 

而且需要確保不會改變,因爲實例對象的結構將在NOSQL數據庫中結束。我認爲__slots__可能會有所幫助,但我需要動態定義它。

有沒有辦法讓它可能沒有元類?

回答

7

使用工廠函數:

def GetTorrentClass(slots_iterable): 
    class Torrent(object): 
     __slots__ = slots_iterable 
    return Torrent 

注意,爲了使用插槽:

  • slots_iterable必須是字符串的迭代
  • 你的類必須是新型
  • 你的班級不能繼承實施__dict__的班級(即只有__slots__

現在,你說'你需要確保不要改變對象的結構',使用__slots__並不是唯一的(也可能不是最好的)解決方案:使用槽使你的班級更難在代碼中使用。

相反,你可以做到以下幾點:

class Torrent(object): 
    def __init__(self, fields): 
     self.fields = fields #Fields could be ('field1', 'field2') 

    def save(self): 
     for field in self.fields: 
      self.store_to_db(field, getattr(self, field)) 

這樣一來,你肯定只有你實際的字段將被保存到你的數據庫。

+0

我需要以更自然的方式訪問代碼中的字段,比如torrent.some_field = some_val,感謝您的幫助。 – loki

+0

如果你不使用'__slots__',你總是可以使用'torrent.some_field = some_val'。在實例化類時,只需在field變量中設置'some_field'(或者它也可以是一個類變量,如果需要更多變量,則可以使用工廠函數)。 –

+0

從字段聲音設置屬性torrent.some_field,它的代碼更多,但速度的增加會證明額外的工作。 – loki

0

__slots____dict__通常是替代品。除了自定義元類可以放寬對__dict__賦值的限制(Django已經這樣​​做)之外,元類無論如何都不會幫助您爲實例動態創建它們。

2

這應該做你需要的魔法。

def construct_slots(slots): 
    class SlotClass(object): 
     __slots__ = slots 
     def __init__(self, *args, **kwargs): 
      for slot, arg in zip(SlotClass.__slots__, args): 
       setattr(self, slot, arg) 
      for key, value in kwargs: 
       setattr(self, key, value) 
    return SlotClass 

Torrent = construct_slots(("a",'b','c')) 
a = Torrent(1,2,3) 
print a.a 
print a.b