2012-05-30 48 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