make a class instance to immutable one. we can call fields, methods, and properties. This airms to make easier to develop multi thread object-oriented programming.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | # -*- coding: utf-8 -*-
"""
immutablize instance sample
"""
import operator
import types
class A(object):
def __init__(self, a, b):
self.a = a
self.__b = b
def say(self):
print self.a,self.__b
def incr(self):
self.a = self.a + 100
def incr2(self):
self.incr()
def frozen_instance(instance):
def new__(_cls, inst):
return tuple.__new__(_cls, tuple([inst] + inst.__dict__.values()))
def repr__(self):
return repr(self[0])
def getattr__(self, name):
return types.MethodType(self[0].__class__.__dict__[name], self, self[0].__class__)
klass = instance.__class__
nlass = type('Frozen'+klass.__name__,(tuple,),
dict(__new__=new__, __repr__=repr__, __getattr__=getattr__)
)
for i,k in enumerate(instance.__dict__.keys()):
setattr(nlass, k, property(operator.itemgetter(1+i)))
return nlass(instance)
if __name__ == '__main__':
a = A(1, "aaa")
print "[a]"
a.say()
frozen_a = frozen_instance(a)
print "[frozen_a]"
frozen_a.say()
a.incr()
a.say()
frozen_a.incr2()
-----outputs-----
[a]
1 aaa
[frozen_a]
1 aaa
101 aaa
Traceback (most recent call last):
File "fix.py", line 58, in <module>
frozen_a.incr2()
File "fix.py", line 22, in incr2
self.incr()
File "fix.py", line 19, in incr
self.a = self.a + 100
AttributeError: can't set attribute
|
Doesn't work for instances with no __dict__.
It also breaks instances with __getitem__.
supported for raw list and dict:
newer sample:
upper sample code outputs the following: [1, 2, 3] 3 1 1 AttributeError: can't set item ['a', 'b'] [1, 2] [('a', 1), ('b', 2)] AttributeError: can't set item AttributeError: can't set item AttributeError: can't set item AttributeError: can't set item AttributeError: can't set item 1 {'a': 1, 'b': 2} 123 2 2