, , ( ). , , , . , namedtuple . namedtuple , namedtuple . abc.ABCMeta, . :
class Foo(object):
__metaclass__ = ImmutableMeta
_attributes_ = 'a b'
def sayhi(self):
print "Hello from {0}".format(type(self).__name__)
class Bar(Foo):
_attributes_ = 'c'
def saybye(self):
print "Goodbye from {0}".format(type(self).__name__)
:
import collections as co
import abc
class ImmutableMeta(abc.ABCMeta):
_classes = {}
def __new__(meta, clsname, bases, clsdict):
attributes = clsdict.pop('_attributes_')
if bases[0] is object:
methods = clsdict
else:
base = bases[0]
attributes = meta._classes[base]['attributes'] + ' ' + attributes
base_methods = meta._classes[base]['methods'].copy()
base_methods.update(clsdict)
methods = base_methods
new_base = co.namedtuple(clsname + 'Base', attributes)
cls = super(ImmutableMeta, meta).__new__(meta, clsname, (new_base,),
methods)
meta._classes[cls] = {'attributes': attributes,
'methods': methods}
if bases[0] is not object:
base.register(cls)
return cls
- .
a = Foo(1, 2)
a.sayhi()
b = Bar(1, 2, 3)
b.sayhi()
b.saybye()
try:
b.c = 1
except AttributeError:
print "Immutable"
print "issubclass(Bar, Foo): {0}".format(issubclass(Bar, Foo))
try:
d = {b: 1}
except TypeError:
print "Cant put it in a dict"
else:
print "Can put it in a dict"
, . , , __getattr__, . - baseclass , , .