Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

change __slots__ dynamically

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 ?

like image 439
loki Avatar asked Sep 05 '25 15:09

loki


1 Answers

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.

like image 92
Thomas Orozco Avatar answered Sep 08 '25 11:09

Thomas Orozco