class TypeSetter(object):
def __init__(self,fieldtype):
print 'TypeSetter set attribute type',fieldtype
self.fieldtype = fieldtype
def is_valid(self,value):
print "TypeSetter is_valid is called"
return isinstance(value,self.fieldtype)
class TypeCheckMeta(type):
def __new__(cls,name,bases,dict):
print '-'*29
print 'Allocating memory for class'
print name
print bases
print dict
print '*' * 29
return super(TypeCheckMeta,cls).__new__(cls,name,bases,dict)
def __init__(cls,name,bases,dict):
cls._fields = {}
for key,value in dict.items():
print '$'*8,key,'>'*8,value
if isinstance(value,TypeSetter):
cls._fields[key]=value
class TypeCheck(object):
__metaclass__ = TypeCheckMeta
def __setattr__(self, key, value):
print 'TypeCheck set attribute value',key,value
if key in self._fields:
if not self._fields[key].is_valid(value):
raise TypeError('Invalid type for field')
super(TypeCheck,self).__setattr__(key,value)
class MetaTest(TypeCheck):
name = TypeSetter(str)
num = TypeSetter(int)
if __name__ == '__main__':
mt = MetaTest()
mt.name = "apple"
mt.num = "test"
输出:
/home/python/.virtualenvs/company_web/bin/python /home/python/project/datacollecting/spider/test_reg.py
-----------------------------
Allocating memory for class
TypeCheck
(<type 'object'>,)
{'__module__': '__main__', '__metaclass__': <class '__main__.TypeCheckMeta'>, '__setattr__': <function __setattr__ at 0x7f2bad626c80>}
*****************************
$$$$$$$$ __module__ >>>>>>>> __main__
$$$$$$$$ __metaclass__ >>>>>>>> <class '__main__.TypeCheckMeta'>
$$$$$$$$ __setattr__ >>>>>>>> <function __setattr__ at 0x7f2bad626c80>
TypeSetter set attribute type <type 'str'>
TypeSetter set attribute type <type 'int'>
-----------------------------
Allocating memory for class
MetaTest
(<class '__main__.TypeCheck'>,)
{'__module__': '__main__', 'num': <__main__.TypeSetter object at 0x7f2bad624a50>, 'name': <__main__.TypeSetter object at 0x7f2bad624a10>}
*****************************
$$$$$$$$ __module__ >>>>>>>> __main__
$$$$$$$$ num >>>>>>>> <__main__.TypeSetter object at 0x7f2bad624a50>
$$$$$$$$ name >>>>>>>> <__main__.TypeSetter object at 0x7f2bad624a10>
TypeCheck set attribute value name apple
TypeSetter is_valid is called
TypeCheck set attribute value num test
TypeSetter is_valid is called
Traceback (most recent call last):
File "/home/python/project/datacollecting/spider/test_reg.py", line 65, in <module>
mt.num = "test"
File "/home/python/project/datacollecting/spider/test_reg.py", line 51, in __setattr__
raise TypeError('Invalid type for field')
TypeError: Invalid type for field
Process finished with exit code 1