change __slots__ dynamically

[亡魂溺海] 提交于 2020-01-02 07:45:08

问题


I'm working on a class that needs to be given it's __dict__ attribute via __init__ injection like this:

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

And need to make sure not to change the structure of the object because the instance is going to end up in a NOSQL db. I thought that __slots__ could be helpful, but I need to define it dynamically.

Is there a way to make it possible without a metaclass ?


回答1:


Use a factory function:

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

Note that in order to use slots:

  • slots_iterable must be an iterable of strings
  • Your class must be new-style
  • Your class can't inherit a class that implements __dict__ (ie. that is not __slots__ only)

Now, you say you 'need to make sure not to change the structure of the object', using __slots__ is not the only (and probably not the best either) solution to your issue: using slots makes your class harder to use in code.

Instead, you could do the following:

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))

This way, you're sure that only your actual fields will be saved to your db.




回答2:


This should do the magic you require.

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



回答3:


__slots__ and __dict__ are usually alternatives. In neither case will a metaclass help you dynamically create them for an instance, except that a custom metaclass can relax the restriction on assignment to __dict__ (Django already does this).



来源:https://stackoverflow.com/questions/10822154/change-slots-dynamically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!