前几天用python写了一个对象池类的代码,可以限制子类的对象生成数量,不同子类的容量是独立的,可动态设置。
源码:(instancepool.py)
测试代码:
注意,在A类定义中,父类的声明顺序是dict,InstancePool,这导致dict.__new__()被调用,而 InstancePool.__new__() (--->object.__new__())没有被调用。这种情况下,InstancePool对A池容量的控制失败。
InstancePool子类定义时遵守以下约定才能保证InstancePool正常工作:
1:子类以InstancPool为第一父类,或者先于InstancePool定义的所有父类(包括它们的祖先)都没有定义__new__函数
2:子类不重定义__new__函数,或在其中间接调用InstancePool.__new__()并返回由 InstancePool.__new__()返回的对象,如:
如果希望在生成多个对象而容量不足时不返回异常,而是尽量满足,可重定义getSome()函数:
源码:(instancepool.py)
class
PoolSizeError:
pass
class InstancePool(object):
__default = 100
def __new__ (cls, * args, ** kwds):
cls. __test_set ()
if cls. __count < cls. __size :
newInstance = object. __new__ (cls)
cls. __count += 1
return newInstance
else :
raise PoolSizeError
def __init__ (self):
pass
def __del__ (self):
self. __class__ . __count -= 1
def __test_set (cls):
try :
cls. __size
except AttributeError:
cls. __size = InstancePool. __default
try :
cls. __count
except AttributeError:
cls. __count = 0
def setSize(cls,num):
cls. __test_set ()
if num < cls. __count :
raise PoolSizeError
else :
cls. __size = num
def getCount(cls):
cls. __test_set ()
return cls. __count
def getSize(cls):
cls. __test_set ()
return cls. __size
def tryGet(cls, num):
cls. __test_set ()
if num > (cls. __size - cls. __count ):
return False
else :
return True
def getAll(cls, * args, ** kwds):
cls. __test_set ()
return [cls( * args, ** kwds) for k in range(cls. __size - cls. __count )]
def getSome(cls, num, * args, ** kwds):
cls. __test_set ()
if num > (cls. __size - cls. __count ):
raise PoolSizeError
return [cls( * args, ** kwds) for k in range(num)]
getCount = classmethod(getCount)
getSize = classmethod(getSize)
setSize = classmethod(setSize)
getAll = classmethod(getAll)
getSome = classmethod(getSome)
__test_set = classmethod( __test_set )
tryGet = classmethod(tryGet)
pass
class InstancePool(object):
__default = 100
def __new__ (cls, * args, ** kwds):
cls. __test_set ()
if cls. __count < cls. __size :
newInstance = object. __new__ (cls)
cls. __count += 1
return newInstance
else :
raise PoolSizeError
def __init__ (self):
pass
def __del__ (self):
self. __class__ . __count -= 1
def __test_set (cls):
try :
cls. __size
except AttributeError:
cls. __size = InstancePool. __default
try :
cls. __count
except AttributeError:
cls. __count = 0
def setSize(cls,num):
cls. __test_set ()
if num < cls. __count :
raise PoolSizeError
else :
cls. __size = num
def getCount(cls):
cls. __test_set ()
return cls. __count
def getSize(cls):
cls. __test_set ()
return cls. __size
def tryGet(cls, num):
cls. __test_set ()
if num > (cls. __size - cls. __count ):
return False
else :
return True
def getAll(cls, * args, ** kwds):
cls. __test_set ()
return [cls( * args, ** kwds) for k in range(cls. __size - cls. __count )]
def getSome(cls, num, * args, ** kwds):
cls. __test_set ()
if num > (cls. __size - cls. __count ):
raise PoolSizeError
return [cls( * args, ** kwds) for k in range(num)]
getCount = classmethod(getCount)
getSize = classmethod(getSize)
setSize = classmethod(setSize)
getAll = classmethod(getAll)
getSome = classmethod(getSome)
__test_set = classmethod( __test_set )
tryGet = classmethod(tryGet)
测试代码:
from instancepool import InstancePool:
class A(dict, InstancePool):
pass
A.setSize( 90 )
class B(InstancePool):
def __init__(self, key):
self.key = key
B.setSize( 203 )
objsetA0 = A.getAll()
print A.getCount() #0
objsetA1 = A.getAll()
print " %d %s are initialized! " % (len(objsetA1), A.__name__) #90
print objsetA[0]
if B.tryGet( 23 ):
objsetB = B.getSome( 23 , ' My Name ' )
print " %d %s are initialized! " % (len(objsetB), B.__name__)
print objsetB[ 0 ].key
class A(dict, InstancePool):
pass
A.setSize( 90 )
class B(InstancePool):
def __init__(self, key):
self.key = key
B.setSize( 203 )
objsetA0 = A.getAll()
print A.getCount() #0
objsetA1 = A.getAll()
print " %d %s are initialized! " % (len(objsetA1), A.__name__) #90
print objsetA[0]
if B.tryGet( 23 ):
objsetB = B.getSome( 23 , ' My Name ' )
print " %d %s are initialized! " % (len(objsetB), B.__name__)
print objsetB[ 0 ].key
注意,在A类定义中,父类的声明顺序是dict,InstancePool,这导致dict.__new__()被调用,而 InstancePool.__new__() (--->object.__new__())没有被调用。这种情况下,InstancePool对A池容量的控制失败。
InstancePool子类定义时遵守以下约定才能保证InstancePool正常工作:
1:子类以InstancPool为第一父类,或者先于InstancePool定义的所有父类(包括它们的祖先)都没有定义__new__函数
2:子类不重定义__new__函数,或在其中间接调用InstancePool.__new__()并返回由 InstancePool.__new__()返回的对象,如:
def
__new__
(cls,
*
args,
**
kwds):
inst = InstancePool. __new__ (cls, * args, ** kwds)
# some operation with inst
return inst
inst = InstancePool. __new__ (cls, * args, ** kwds)
# some operation with inst
return inst
如果希望在生成多个对象而容量不足时不返回异常,而是尽量满足,可重定义getSome()函数:
def
getSome(cls, num,
*
args,
**
kwds):
cls. __test_set ()
if num > (cls. __size - cls. __count ):
return cls.getAll( * args, ** kwds)
return [cls( * args, ** kwds) for k in range(num)]
cls. __test_set ()
if num > (cls. __size - cls. __count ):
return cls.getAll( * args, ** kwds)
return [cls( * args, ** kwds) for k in range(num)]