If the created class has a property of type dict
, and you do not want to change the property element without permission, we will explain how to prevent the property element from being changed using MappingProxyType.
For example, assume the following code.
python
class Foo:
def __init__(self):
self._bar = {'a': 1, 'b': 2}
@property
def bar(self):
return self._bar
def add_item(self, key, value):
#I want the user to add the element only through this method
self._bar[key] = value
In this code, the Foo class property bar
does not have a setter
defined, so the user cannot change bar
to another object. Attempting to set a different value for bar
will result in an error, as follows:
python
>>> foo = Foo()
>>> foo.bar
{'b': 2, 'a': 1}
>>> foo.bar = 1
Traceback (most recent call last):
File "<pyshell#15>", line 1, in <module>
foo.bar = 1
AttributeError: can't set attribute
However, since foo.bar
itself is a dict, you can add elements.
python
>>> foo.bar['c'] = 3
>>> foo.bar
{'b': 2, 'a': 1, 'c': 3}
In order to prevent unintentional changes of the creator of such a class, there is a way to use the MappingProxyType
type of the types
library in Python Ver 3.3 or later. If you use the MappingProxyType constructor and return the returned dictionary as a mapping proxy object, the user will not be able to modify the returned object. If you change the sample earlier, it will look like this.
python
from types import MappingProxyType
class Foo:
def __init__(self):
self._bar = {'a': 1, 'b': 2}
@property
def bar(self):
return MappingProxyType(self._bar)
def add_item(self, key, value):
self._bar[key] = value
If the user tries to add an element to bar as follows, an error will occur.
python
>>> foo = Foo()
>>> foo.bar
mappingproxy({'a': 1, 'b': 2})
>>> foo.bar['c'] = 3 #Attempting to add an element will result in an error.
Traceback (most recent call last):
File "<pyshell#29>", line 1, in <module>
foo.bar['c'] = 3
TypeError: 'mappingproxy' object does not support item assignment
>>> foo.add_item('c', 3) #The user adds an element using a method.
>>> foo.bar
mappingproxy({'a': 1, 'c': 3, 'b': 2})
mappingproxy
can be used as a read-only
dictionary because you can get elements in the same way as dict
.
Recommended Posts