【问题标题】:change __slots__ dynamically动态更改 __slots__
【发布时间】:2023-03-09 12:23:01
【问题描述】:

我正在研究一个需要通过__init__ 注入赋予其__dict__ 属性的类,如下所示:

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

并且需要确保不要更改对象的结构,因为实例最终会在 NOSQL 数据库中。我认为__slots__ 可能会有所帮助,但我需要动态定义它。

有没有办法在没有元类的情况下实现它?

【问题讨论】:

    标签: python class dictionary


    【解决方案1】:

    使用工厂函数:

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

    这样,您可以确定只有您的实际字段会保存到您的数据库中。

    【讨论】:

    • 我需要以更自然的方式从代码中访问字段,例如 torrent.some_field = some_val,感谢您的帮助。
    • 如果您不使用__slots__,您可以始终使用torrent.some_field = some_val。实例化类时,只需在 fields 变量中设置 some_field(或者它也可以是类变量,如果需要更多可变性,可以使用工厂函数)。
    • 从字段中设置一个属性 torrent.some_field 听起来和它的代码更多,但速度的提高将证明额外的工作是合理的。
    • 我不太明白你的意思。在这里,fields 变量的唯一用途是让 save 方法识别它应该保存到数据库的字段。
    【解决方案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
    

    【讨论】:

      【解决方案3】:

      __slots____dict__ 通常是备选方案。在这两种情况下,元类都不会帮助您为实例动态创建它们,除非自定义元类可以放宽对__dict__ 的分配限制(Django 已经这样做了)。

      【讨论】:

        猜你喜欢
        • 2015-03-10
        • 2015-06-29
        • 1970-01-01
        • 1970-01-01
        • 2013-06-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多