dinamically altering a function
Bengt Richter
bokr at oz.net
Sun Mar 13 01:23:32 EST 2005
On Sat, 12 Mar 2005 23:09:58 -0400, vegetax <vegeta.z at gmail.com> wrote:
>Bengt Richter wrote:
[...]
>> Please pretend things worked the way you want, and post an example. Maybe
>> we can make it work.
>>
>> Regards,
>> Bengt Richter
>
>Ok , the complete use case is :
>
>def fun1(a,b,obj = None):
> isSuplied = 1
> if not obj :
> obj = generateObject()
> isSuplied = 0
>
> <do something with obj>
>
> if not isSuplied : obj.dispose()
>
>def fun2(c,obj = None):
> isSuplied = 1
> if not obj :
> obj = generateObject()
> isSuplied = 0
>
> <do something else with obj>
>
> if not isSuplied : obj.dispose()
>
>So , maybe i will need to define fun3 later,i dont know , but fun3 also will
>work with "obj".
>So the thing is to try to factorize the code,so that it is in the decorator:
>
>def dec(func):
> def wrapper(*arg,**kw):
> obj = kw.get('obj',None)
> isSuplied = 1
> if not obj :
> obj = generateObject()
> kw['obj'] = obj
> isSuplied = 0
>
> res = func(*arg,**kw)
> if not isSuplied : obj.dispose()
> return res
>
> return wrapper
>
>so the previous function declarations, will look like:
>
>@dec
>def fun1(a,b,obj = None):
> <do something with obj>
>
>@dec
>def fun2(c,obj = None):
> <do something with obj>
>
>but i have to define obj = None in each function,but the functions should
>know they will have an obj instance available, so the byte code hack would
>be :
>
>def dec(func):
> def wrapper(*arg,**kw):
> obj = kw.get('obj',None)
> isSuplied = 1
> if not obj :
> obj = generateObject()
> isSuplied = 0
>
> << BIND OBJ TO THE FUNCTION LOCAL NAMESPACE >>
>
> res = func(*arg,**kw)
> if not isSuplied : obj.dispose()
> return res
>
> return wrapper
>
>so the functions knowing they will be altered(added an instance of obj),they
>will just need to define their own arguments only.
>
>@dec
>fun1(a,b) : obj.result = a + b
>@dec
>fun2(c) : obj.result = c * 4
>
>So the duplication would be removed.
>
>But i realized the best aproach,is a callable class that provides that
>infrastructure, or not? =P
>
Maybe this implements what you are asking for?
----< vegetax.py >-------------------------
from ut.presets import presets
class generateObject(object):
def dispose(self): print 'disposing of %r: %r' %(self, vars(self))
def dec(func):
def getfun(f): return func # fake decorator to pass func to presets
def wrapper(*arg,**kw):
obj = kw.get('obj',None)
isSuplied = 1
if not obj :
obj = generateObject()
isSuplied = 0
else:
del kw['obj'] # don't pass unexpected kwarg to func
#<< BIND OBJ TO THE FUNCTION LOCAL NAMESPACE >>
@presets(obj=obj) # per comment above
@getfun
def funcalias(): pass # just for a local name to bind
res = funcalias(*arg, **kw)
if not isSuplied : obj.dispose()
return res
return wrapper
#so the functions knowing they will be altered(added an instance of obj),they
#will just need to define their own arguments only.
if __name__ == '__main__':
@dec
def fun1(a,b) : obj.result = a + b; return obj, vars(obj)
@dec
def fun2(c) : obj.result = c * 4; return obj, vars(obj)
o, v = fun1(111, 222) # bind obj to show that new obj is generated on next call
print o, v
print fun2(1111)
print 'supplying obj to fun2:', fun2(2222, obj=generateObject()) # supplied
print 'both ways:', (fun2(1111), fun2(2222, obj=generateObject()))
-------------------------------------------
[22:21] C:\pywk\clp>py24 vegetax.py
disposing of <__main__.generateObject object at 0x02EF9F0C>: {'result': 333}
<__main__.generateObject object at 0x02EF9F0C> {'result': 333}
disposing of <__main__.generateObject object at 0x02EF33CC>: {'result': 4444}
(<__main__.generateObject object at 0x02EF33CC>, {'result': 4444})
supplying obj to fun2: (<__main__.generateObject object at 0x02EF33CC>, {'result': 8888})
both ways: disposing of <__main__.generateObject object at 0x02EF33CC>: {'result': 4444}
((<__main__.generateObject object at 0x02EF33CC>, {'result': 4444}), (<__main__.generateObject o
bject at 0x02EF316C>, {'result': 8888}))
Regards,
Bengt Richter
More information about the Python-list
mailing list