Egy ehhez hasonlot akartam eloszor csinalni, de class decorator (meg?) nincs pythonban igy a syntax ezt nem engedi meg.
@implements( [IInterface1, IInterface2] ) # not supported
class Test:
...
Ezert fuggveny decoratorral probalkoztam. Konstruktort altalban explicit megadja az ember igy erre huztam ra a decorator fuggvenyt. A problema ezzel hogy peldanyositaskor ellenorzi, nem pedig a modul betoltesekor, igy csak runtime derul ki ha baj van. (De talan hamarabb mintha metodus hivasnal jonnenk ra hogy nem letezik az adott fuggveny)
class ITest:
def testMethod(self): pass
class Cloneable:
def clone(): pass
class Test:
@implements( (ITest, Cloneable) )
def __init__(self, s, i):
print s, i
def testMethod(self):
print 'implemented'
def clone(self):
print 'clone test'
t = Test( 'test', 1 )
t.testMethod()
t.clone()
A konstruktorra kell hattatni a decoratort, ami visszad egy olyan fuggvenyt ami leellenorzi az implementaciot es meghivja az eredeti konstruktort. A tovabbi problema ezzel hogy minden egyes peldanyositaskor lefut az ellenorzes, es feleslegesen lassit. Ezt esetleg meg lehetne oldani egy global release/debug flaggel amit ha kikapcsol az ember akkor skipeli az ellenorzest. Ha valami static initializacios blokkba el lehetne helyezni hasonlo modon az ellenorzest es ugy a modul importalasanal le tudna ellenorizni akkor hasznalhato lenne. Ha valakinek van erre hasznalhato otlete az irja meg plz.
A decorator amit en hasznaltam a kovetkezo:
def implements( infaces ):
"""
implements decorator
usage:
class Sample:
@implements( (IInterface1, IInterface2, IInterfaceN )
def __init__(self, args):
...
warning: this will check the implementation at runtime, before every creation of the instance
"""
def f( init ):
from types import MethodType
def getMethods( clz ):
return [i for i in dir(clz) if type(getattr(clz, i)) == MethodType]
def checkInterface( clazz ):
cmethods = getMethods( clazz )
for inf in infaces:
imethods = getMethods( inf )
for i in imethods:
assert i in cmethods, `i` + ' not correctly implemented'
def new_init(ref, *args, **kargs): # this will be the new constructor
checkInterface( ref.__class__ )
return init(ref, *args, **kargs)
return new_init
return f

0 comments:
Post a Comment