python - 在 Python 中创建不可变对象
问题描述
我想在 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__dict__
在评论中提到的那样,通过实现来阻止访问__getattr__
。
我已经实施了以下解决方案并且它有效
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
解决方案
您可以将您想要的唯一属性添加到插槽中,如下所示
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__'
推荐阅读
- html - 如何返回 HttpResponse(编写和下载 csv)并重定向到 Html 页面
- c++ - 在 C++ 中创建“通用”结构
- android - 是否可以在 React Native 中拥有 SQL 数据库?
- karate - 如何在空手道中验证 json 未命名数组
- scala - 我可以使用相同的火花上下文使用演员编写不同的文件吗?
- c++ - 我不能用 C++ 编译 Xcode 库
- javascript - Cordova 插件媒体音频速度
- protractor - 使用量角器运行的codeceptjs不会退出
- angular - ng2-smart-table 在编辑点击时打开弹出窗口
- java - 在 java 8 中运行时更新外部属性