【问题标题】:Create Immutable Object in Python [duplicate]在 Python 中创建不可变对象 [重复]
【发布时间】:2020-01-14 14:30:48
【问题描述】:

我想在 python 中创建一个像字典一样的不可变类。我在 stackoverflow 上找到了以下解决方案,但是这个对象的值可以通过使用 __dict__.update 函数来更新。有没有办法阻止这个动作。

class Immutable(object):
    def __init__(self, **kwargs):
        """Sets all values once given
        whatever is passed in kwargs
        """
        for k, v in kwargs.items():
            object.__setattr__(self, k, v)

    def __setattr__(self, *args):
        """Disables setting attributes via
        item.prop = val or item['prop'] = val
        """
        raise TypeError('Immutable objects cannot have properties set after init')

    def __delattr__(self, *args):
        """Disables deleting properties"""
        raise TypeError('Immutable objects cannot have properties deleted')


x = Immutable(a=5)
print(x.a) # 5 as expected
x.__dict__.update({'a': 7}) # should raise error or update copy of x
print(x.a) # 7, thus object is still mutable

解决方案

正如DeepSpace 在评论中提到的那样,通过实现__getattr__ 来阻止对__dict__ 的访问。

我已经实施了以下解决方案并且它有效

class Immutable(object):
    def __init__(self, **kwargs):
        """Sets all values once given
        whatever is passed in kwargs
        """
        for k, v in kwargs.items():
            object.__setattr__(self, k, v)

    def __getattribute__(self, item):
        result = super(Immutable, self).__getattribute__(item)
        if item == '__dict__':
            return dict(**result)
        return result

    def __setattr__(self, *args):
        """Disables setting attributes via
        item.prop = val or item['prop'] = val
        """
        raise TypeError('Immutable objects cannot have properties set after init')

    def __delattr__(self, *args):
        """Disables deleting properties"""
        raise TypeError('Immutable objects cannot have properties deleted')


x = Immutable(a=5)
print(x.a) # 5
x.__dict__.update({'a': 7}) # update value on a copy of dict which has no effect
print(x.a) # 5 this time object value remain same

【问题讨论】:

标签: python python-3.x immutability


【解决方案1】:

您可以在 slot 中添加您想要在您的类中的唯一属性,如下所示

class Immutable(object):
    def __init__(self, **kwargs):
        """Sets all values once given
        whatever is passed in kwargs
        """
        for k, v in kwargs.items():
            object.__setattr__(self, k, v)

    def __setattr__(self, *args):
        """Disables setting attributes via
        item.prop = val or item['prop'] = val
        """
        raise TypeError('Immutable objects cannot have properties set after init')

    def __delattr__(self, *args):
        """Disables deleting properties"""
        raise TypeError('Immutable objects cannot have properties deleted')

    __slots__ =('k')


x = Immutable(k=5)
print(x.k) # 5 as expected
x.__dict__.update({'k': 7}) # should raise error or update copy of x
print(x.a) # 7, thus object is still mutable

输出

5
Traceback (most recent call last):
  File "inmutable.py", line 24, in <module>
    x.__dict__.update({'k': 7}) # should raise error or update copy of x
AttributeError: 'Immutable' object has no attribute '__dict__'

【讨论】:

  • 这并不能解决我的问题,因为我不希望类中的属性数量固定,并且添加插槽后我无法添加任意属性。
  • 只是给你另一种选择。我认为您发布的答案是大部分时间都应该使用的答案,也适用于您的情况,除非您正在寻找一些内存优化,因为您正在创建数百万个这种不可变对象。
猜你喜欢
  • 1970-01-01
  • 2015-04-02
  • 2021-05-04
  • 1970-01-01
  • 2019-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多