Passing function to a class - python

I have created a class that can take a function with a set of arguments. I would like to run the passed function every time the event handler signals.
I am attaching my code below which runs when I pass a fun2 which has no arguments but not with fun1. Any suggestions that I can make to the code below work with fun1 and fun2? If I omit the return statement from fun1, I get an error that 'str' object is not callable.
>>> TimerTest.main()
function 1. this function does task1
my function from init from function1
my function in start of runTimerTraceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Program Files (x86)\IronPython 2.7\TimerTest.py", line 57, in main
File "C:\Program Files (x86)\IronPython 2.7\TimerTest.py", line 25, in runTime
r
TypeError: str is not callable
import System
from System.Timers import (Timer, ElapsedEventArgs)
class timerTest:
def __init__ (self, interval,autoreset, fun):
self.Timer = Timer()
self.Timer.Interval= interval
self.Timer.AutoReset = autoreset
self.Timer.Enabled = True
self.myfunction = fun
def runTimer(self):
print 'my function in start of runTimer', self.myfunction ()
self.Timer.Start()
def OnTimedEvent (s, e):
print "The Elapsed event was raised at " , e.SignalTime
print 'printing myfunction...', self.myfunction()
self.myfunction()
self.Timer.Elapsed += OnTimedEvent
def stopTimer(self):
self.Timer.Stop()
self.Timer.Dispose= True
def fun1(a,b):
print 'function 1. this function does task1'
return 'from function1'
def fun2():
print 'Function 2. This function does something'
print 'Test 1...2...3...'
return 'From function 2'
def main():
a = timerTest(1000, True, fun1(10,20))
a.runTimer()
b= timerTest(3000,True,fun2)
b.runTimer()
if __name__ == '__main__':
main()
I am learning Python and I apologize if my questions are basic.
To change the interval, I stop the timer using a stopTimer method I added to the timerTest class:
def stopTimer(self):
self.Timer.Stop()
I take the new user input to call the runTimer method which I have revised per Paolo Moretti's suggestions:
def runTimer(self, interval,autoreset,fun,arg1, arg2, etc.):
self.Timer.Interval= interval
self.Timer.AutoReset = autoreset
myfunction = fun
my_args = args
self.Timer.Start()
def OnTimedEvent (s, e):
print "The Elapsed event was raised at " , e.SignalTime
myfunction(*my_args)
self.Timer.Elapsed += OnTimedEvent
Whenever a command button is pressed, the following method is called:
requestTimer.runTimer((self.intervalnumericUpDown.Value* 1000),True, function, *args)
I do not understand why stopping the timer and sending the request causes the runTimer method to be executed multiple times and it seems dependent on how many times I change the interval. I have tried a couple of methods: Close and Dispose with no success.
A second question on slightly different subject.
I have been looking at other .NET classes with Timer classes. A second question is on how I would translate the following VB sample code into Python. Is "callback As TimerCallback" equivalent to myfunction(*my_args)?
Public Sub New ( _
callback As TimerCallback, _
state As Object, _
dueTime As Integer, _
period As Integer _
)
per .NET documentation:
callback
Type: System.Threading.TimerCallback
A TimerCallback delegate representing a method to be executed.
I can partially get the timer event to fire if I define a function with no arguments such as:
def fun2(stateinfo):
# function code
which works with:
self.Timer = Timer(fun2, self.autoEvent, self.dueTime,self.period)
The function call fails if I replace fun2 with a more generic function call myfunction(*my_args)

You can also use * syntax for calling a function with an arbitrary argument list:
class TimerTest:
def __init__(self, interval, autoreset, fun, *args):
# ...
self.my_function = fun
self.my_args = args
# ...
def run_timer(self):
# ...
def on_timed_event(s, e):
# ...
self.my_function(*self.my_args)
# ...
Usage:
>>> t1 = TimerTest(1000, True, fun1, 10, 20)
>>> t2 = TimerTest(1000, True, fun2)
And check out the PEP8 style guide as well. Python's preferred coding conventions are different than many other common languages.
Question 1
Every time you use the addition assignment operator (+=) you are attaching a new event handler to the event. For example this code:
timer = Timer()
def on_timed_event(s, e):
print "Hello form my event handler"
timer.Elapsed += on_timed_event
timer.Elapsed += on_timed_event
timer.Start()
will print the "Hello form my event handler"phrase twice.
For more information you can check out the MSDN documentation, in particular Subscribe to and Unsubscribe from Events .
So, you should probably move the event subscription to the __init__ method, and only start the timer in your run_timer method:
def run_timer(self):
self.Timer.Start()
You could also add a new method (or use a property) for changing the interval:
def set_interval(self, interval):
self.Timer.Interval = interval
Question 2
You are right about TimerCallback: it's a delegate representing a method to be executed.
For example, this Timer constructor:
public Timer(
TimerCallback callback
)
is expecting a void function with a single parameter of type Object.
public delegate void TimerCallback(
Object state
)
When you are invoking a function using the * syntax you are doing something completely different. It's probably easier if I'll show you an example:
def foo(a, b, *args):
print a
print b
print args
>>> foo(1, 2, 3, 4, 5)
1
2
(3, 4, 5)
>>> args = (1, 2, 3)
>>> foo(1, 2, *args)
1
2
(1, 2, 3)
Basically in the second case you are invoking a function with additional arguments unpacked from a tuple.
So If you want to pass a function with a different signature to a constructor which accepts a TimerCallback delegate you have to create a new function, like #Lasse is suggesting.
def my_func(state, a, b):
pass
You can do this either using the lambda keyword:
t1 = Timer(lambda state: my_func(state, 1, 2))
or by declaring a new function:
def time_proc(state):
my_func(state, 1, 2)
t2 = Timer(time_proc)

If the function takes no parameters, simply pass it without calling it:
b = timerTest(3000, True, fun2)
If it takes parameters, you need to convert it to a function that doesn't take parameters. What you're doing is calling it, and then you pass the result, which in this case is a string. Instead do this:
a = timerTest(1000, True, lambda: fun1(10, 20))

Related

get the last function call in the continuous calling (chain of function calls) - Python [duplicate]

How could one write a debounce decorator in python which debounces not only on function called but also on the function arguments/combination of function arguments used?
Debouncing means to supress the call to a function within a given timeframe, say you call a function 100 times within 1 second but you only want to allow the function to run once every 10 seconds a debounce decorated function would run the function once 10 seconds after the last function call if no new function calls were made. Here I'm asking how one could debounce a function call with specific function arguments.
An example could be to debounce an expensive update of a person object like:
#debounce(seconds=10)
def update_person(person_id):
# time consuming, expensive op
print('>>Updated person {}'.format(person_id))
Then debouncing on the function - including function arguments:
update_person(person_id=144)
update_person(person_id=144)
update_person(person_id=144)
>>Updated person 144
update_person(person_id=144)
update_person(person_id=355)
>>Updated person 144
>>Updated person 355
So calling the function update_person with the same person_id would be supressed (debounced) until the 10 seconds debounce interval has passed without a new call to the function with that same person_id.
There's a few debounce decorators but none includes the function arguments, example: https://gist.github.com/walkermatt/2871026
I've done a similar throttle decorator by function and arguments:
def throttle(s, keep=60):
def decorate(f):
caller = {}
def wrapped(*args, **kwargs):
nonlocal caller
called_args = '{}'.format(*args)
t_ = time.time()
if caller.get(called_args, None) is None or t_ - caller.get(called_args, 0) >= s:
result = f(*args, **kwargs)
caller = {key: val for key, val in caller.items() if t_ - val > keep}
caller[called_args] = t_
return result
# Keep only calls > keep
caller = {key: val for key, val in caller.items() if t_ - val > keep}
caller[called_args] = t_
return wrapped
return decorate
The main takaway is that it keeps the function arguments in caller[called_args]
See also the difference between throttle and debounce: http://demo.nimius.net/debounce_throttle/
Update:
After some tinkering with the above throttle decorator and the threading.Timer example in the gist, I actually think this should work:
from threading import Timer
from inspect import signature
import time
def debounce(wait):
def decorator(fn):
sig = signature(fn)
caller = {}
def debounced(*args, **kwargs):
nonlocal caller
try:
bound_args = sig.bind(*args, **kwargs)
bound_args.apply_defaults()
called_args = fn.__name__ + str(dict(bound_args.arguments))
except:
called_args = ''
t_ = time.time()
def call_it(key):
try:
# always remove on call
caller.pop(key)
except:
pass
fn(*args, **kwargs)
try:
# Always try to cancel timer
caller[called_args].cancel()
except:
pass
caller[called_args] = Timer(wait, call_it, [called_args])
caller[called_args].start()
return debounced
return decorator
I've had the same need to build a debounce annotation for a personal project, after stumbling upon the same gist / discussion you have, I ended up with the following solution:
import threading
def debounce(wait_time):
"""
Decorator that will debounce a function so that it is called after wait_time seconds
If it is called multiple times, will wait for the last call to be debounced and run only this one.
"""
def decorator(function):
def debounced(*args, **kwargs):
def call_function():
debounced._timer = None
return function(*args, **kwargs)
# if we already have a call to the function currently waiting to be executed, reset the timer
if debounced._timer is not None:
debounced._timer.cancel()
# after wait_time, call the function provided to the decorator with its arguments
debounced._timer = threading.Timer(wait_time, call_function)
debounced._timer.start()
debounced._timer = None
return debounced
return decorator
I've created an open-source project to provide functions such as debounce, throttle, filter ... as decorators, contributions are more than welcome to improve on the solution I have for these decorators / add other useful decorators: decorator-operations repository

Using Python decorators to enable/disable certain parts of a program

I have a bunch of scripts that are essentially data preparation steps, to set up data for simulation models. I very often want to run only parts of it, say either 'phase1' or 'phase2', but most 'phases' are more than one line, so commenting out isn't very convenient. So I generally do:
# Phase 1
if True:
do_step_1('high')
do_step_2()
for i in range(1,10):
do_step_3()
#Phase 2
if True:
do_step_1('low')
do_something_else()
And then change True to False as needed.
Now, this is quite cumbersome. Sometimes, phases depend on each other (so when I run 3 I also need to run 1), they are nested, etc.
What I want to do, is have some way to pass an argument to my script that would run one or more 'phases', and I need some way to 'mark' certain functions, blocks of code or scopes as being part of that 'phase'. A certain chunk of code can be part of multiple phases, so that when there are chunks B and C that depend on chunk A, I could mark A as being part of 'phase1' and 'phase2' and then when I run phase1, it would run chunk A and chunkB, and for phase2, chunk A and chunk C. I hope this still makes sense.
So I was thinking that decorators would be perfect to do this, so that I could do (conceptually) something like
#partOfAPhase("phase1", "phase2")
def f1():
pass
and then somehow, I pass a list of 'phases' to run to my program (either from the command line, or by setting it as a configuration variable somewhere) and when my program is run, it only executes the functions that were decorated as being part of one of the phases specified to be run.
So, what I think I need is a generic decorator that can be applied to either functions or member functions which accept any number of arguments, and I need to be able to pass a list of 'tags' to the decorator itself. Then inside the decorator, I need to check (when the original function or member is called) whether the tags of that decorator exist in a global (maybe class static?) list of tags to run.
I looked at https://gist.github.com/Zearin/2f40b7b9cfc51132851a and it seems, at the very end, to do more or less what I want, yet I can't quite puzzle all pieces together to do what I want. More specifically I don't really understand the double nested decorator generator and whether I would need two functions or just one to implement this, and also how I'd get access to the argument that are passed to the decorator (i.e. the phases to run).
Not sure if this covers your needs but here is a quick and dirty proof of concept:
# This first part could go in its own module or a class or whatever
_program = []
def partOfPhase(*phases):
def decorator(fn):
_program.append((fn, tuple(phases)))
return fn
return decorator
def partOfProgram(fn):
_program.append((fn, None))
return fn
def runProgram(phase):
for fn, fn_phases in _program:
if fn_phases is None or any(p in fn_phases for p in phases):
fn()
# This is the actual script
import sys
#partOfPhase('phase1')
def step1():
print('step1')
#partOfPhase('phase1', 'phase2')
def step2():
print('step2')
#partOfProgram
def step3():
print('step3')
#partOfPhase('phase2')
def step4():
print('step4')
if __name__ == '__main__':
phases = sys.argv[1:]
runProgram(phases)
If you save it as phases.py, for example, you would get:
> python phases.py
step3
> python phases.py phase1
step1
step2
step3
> python phases.py phase2
step3
step4
> python phases.py phase1 phase2
step1
step2
step3
step4
EDIT
I think this is probably more like what you were thinking, functions that become disabled depending on the phase:
# This first part could go in its own module or a class or whatever
from functools import wraps
_enabledPhases = []
def enablePhase(*phases):
_enabledPhases.extend(phases)
def partOfPhase(*phases):
def decorator(fn):
#wraps(fn) # Just "cosmetic" wrapping
def decorated(*args, **kwargs):
if any(p in phases for p in _enabledPhases):
fn(*args, **kwargs)
return decorated
return decorator
# This is the actual script
import sys
#partOfPhase('phase1')
def step1():
print('step1')
#partOfPhase('phase1', 'phase2')
def step2():
print('step2')
def step3():
print('step3')
#partOfPhase('phase2')
def step4():
print('step4')
if __name__ == '__main__':
phases = sys.argv[1:]
enablePhase(*phases)
step1()
step2()
step3()
step4()
Here's what I ended up with, after finding out that the method as it is presented in the link is very convoluted and it's much easier to do this with a callable decorator object. This works on both free standing functions and methods, that take any number of arguments (with some simple tests that just print easily visually verified results):
import functools
import sys
class runConditional(object):
def __init__(self, datasets):
self.datasets = datasets
def __call__(self, func):
def wrapped_f(*args, **kwargs):
global to_run
for d in self.datasets:
if d in to_run:
sys.stdout.write(" 1")
func(*args, **kwargs)
return
sys.stdout.write(" 0")
return wrapped_f
#runConditional([1])
def fun1():
pass
#runConditional([2])
def fun2():
pass
#runConditional([1,2,3])
def fun3(arg1, arg2):
pass
def fun_always():
sys.stdout.write(" 1")
pass
#runConditional([])
def fun_never():
pass
class test():
#runConditional([1])
def m1(self):
pass
#runConditional([2])
def m2(self):
pass
#runConditional([1,2,3])
def m3(self, arg1):
pass
def m_always(self):
sys.stdout.write(" 1")
pass
#runConditional([])
def m_never(self):
pass
def run_test(funcs_to_run, expected):
global to_run
t = test()
funcs = [ fun1, fun2, functools.partial(fun3, "123", "meh"), fun_always, fun_never,
t.m1, t.m2, functools.partial(t.m3, "321"), t.m_always, t.m_never ]
to_run = funcs_to_run
print "Expected: " + " ".join(map(str, expected))
sys.stdout.write("Actual: ")
for f in funcs:
f()
print ""
print ""
run_test([2], [ 0, 1, 1, 1, 0, 0, 1, 1, 1, 0 ])
run_test([1], [ 1, 0, 1, 1, 0, 1, 0, 1, 1, 0 ])
run_test([], [ 0, 0, 0, 1, 0, 0, 0, 0, 1, 0 ])
run_test([1, 2], [ 1, 1, 1, 1, 0, 1, 1, 1, 1, 0 ])

How can I split a long function into separate steps while maintaining the relationship between said steps?

I have a very long function func which takes a browser handle and performs a bunch of requests and reads a bunch of responses in a specific order:
def func(browser):
# make sure we are logged in otherwise log in
# make request to /search and check that the page has loaded
# fill form in /search and submit it
# read table of response and return the result as list of objects
Each operation require a large amount of code due to the complexity of the DOM and they tend to grow really fast.
What would be the best way to refactor this function into smaller components so that the following properties still hold:
the execution flow of the operations and/or their preconditions is guaranteed just like in the current version
the preconditions are not checked with asserts against the state, as this is a very costly operation
func can be called multiple times on the browser
?
Just wrap the three helper methods in a class, and track which methods are allowed to run in an instance.
class Helper(object):
def __init__(self):
self.a = True
self.b = False
self.c = False
def funcA(self):
if not self.A:
raise Error("Cannot run funcA now")
# do stuff here
self.a = False
self.b = True
return whatever
def funcB(self):
if not self.B:
raise Error("Cannot run funcB now")
# do stuff here
self.b = False
self.c = True
return whatever
def funcC(self):
if not self.C:
raise Error("Cannot run funcC now")
# do stuff here
self.c = False
self.a = True
return whatever
def func(...):
h = Helper()
h.funcA()
h.funcB()
h.funcC()
# etc
The only way to call a method is if its flag is true, and each method clears its own flag and sets the next method's flag before exiting. As long as you don't touch h.a et al. directly, this ensures that each method can only be called in the proper order.
Alternately, you can use a single flag that is a reference to the function currently allowed to run.
class Helper(object):
def __init__(self):
self.allowed = self.funcA
def funcA(self):
if self.allowed is not self.funcA:
raise Error("Cannot run funcA now")
# do stuff
self.allowed = self.funcB
return whatever
# etc
Here's the solution I came up with. I used a decorator (closely related to the one in this blog post) which only allows for a function to be called once.
def call_only_once(func):
def new_func(*args, **kwargs):
if not new_func._called:
try:
return func(*args, **kwargs)
finally:
new_func._called = True
else:
raise Exception("Already called this once.")
new_func._called = False
return new_func
#call_only_once
def stateA():
print 'Calling stateA only this time'
#call_only_once
def stateB():
print 'Calling stateB only this time'
#call_only_once
def stateC():
print 'Calling stateC only this time'
def state():
stateA()
stateB()
stateC()
if __name__ == "__main__":
state()
You'll see that if you re-call any of the functions, the function will throw an Exception stating that the functions have already been called.
The problem with this is that if you ever need to call state() again, you're hosed. Unless you implement these functions as private functions, I don't think you can do exactly what you want due to the nature of Python's scoping rules.
Edit
You can also remove the else in the decorator and your function will always return None.
Here a snippet I used once for my state machine
class StateMachine(object):
def __init__(self):
self.handlers = {}
self.start_state = None
self.end_states = []
def add_state(self, name, handler, end_state=0):
name = name.upper()
self.handlers[name] = handler
if end_state:
self.end_states.append(name)
def set_start(self, name):
# startup state
self.start_state = name
def run(self, **kw):
"""
Run
:param kw:
:return:
"""
# the first .run call call the first handler with kw keywords
# each registered handler should returns the following handler and the needed kw
try:
handler = self.handlers[self.start_state]
except:
raise InitializationError("must call .set_start() before .run()")
while True:
(new_state, kw) = handler(**kw)
if isinstance(new_state, str):
if new_state in self.end_states:
print("reached ", new_state)
break
else:
handler = self.handlers[new_state]
elif hasattr(new_state, "__call__"):
handler = new_state
else:
return
The use
class MyParser(StateMachine):
def __init__(self):
super().__init__()
# define handlers
# we can define many handler as we want
self.handlers["begin_parse"] = self.begin_parse
# define the startup handler
self.set_start("begin_parse")
def end(self, **kw):
logging.info("End of parsing ")
# no callable handler => end
return None, None
def second(self, **kw):
logging.info("second ")
# do something
# if condition is reach the call `self.end` handler
if ...:
return self.end, {}
def begin_parse(self, **kw):
logging.info("start of parsing ")
# long process until the condition is reach then call the `self.second` handler with kw new keywords
while True:
kw = {}
if ...:
return self.second, kw
# elif other cond:
# return self.other_handler, kw
# elif other cond 2:
# return self.other_handler 2, kw
else:
return self.end, kw
# start the state machine
MyParser().run()
will print
INFO:root:start of parsing
INFO:root:second
INFO:root:End of parsing
You could use local functions in your func function. Ok, they are still declared inside one single global function, but Python is nice enough to still give you access to them for tests.
Here is one example of one function declaring and executing 3 (supposedly heavy) subfunctions. It takes one optional parameter test that when set to TEST prevent actual execution but instead gives external access to individual sub-functions and to a local variable:
def func(test=None):
glob = []
def partA():
glob.append('A')
def partB():
glob.append('B')
def partC():
glob.append('C')
if (test == 'TEST'):
global testA, testB, testC, testCR
testA, testB, testC, testCR = partA, partB, partC, glob
return None
partA()
partB()
partC()
return glob
When you call func, the 3 parts are executed in sequence. But if you first call func('TEST'), you can then access the local glob variable as testCR, and the 3 subfunctions as testA, testB and testC. This way you can still test individually the 3 parts with well defined input and control their output.
I would insist on the suggestion given by #user3159253 in his comment on the original question:
If the sole purpose is readability I would split the func into three "private" > or "protected" ones (i.e. _func1 or __func1) and a private or protected property > which keeps the state shared between the functions.
This makes a lot of sense to me and seems more usual amongst object oriented programming than the other options. Consider this example as an alternative:
Your class (teste.py):
class Test:
def __init__(self):
self.__environment = {} # Protected information to be shared
self.public_stuff = 'public info' # Accessible to outside callers
def func(self):
print "Main function"
self.__func_a()
self.__func_b()
self.__func_c()
print self.__environment
def __func_a(self):
self.__environment['function a says'] = 'hi'
def __func_b(self):
self.__environment['function b says'] = 'hello'
def __func_c(self):
self.__environment['function c says'] = 'hey'
Other file:
from teste import Test
t = Test()
t.func()
This will output:
Main function says hey guys
{'function a says': 'hi', 'function b says': 'hello', 'function c says': 'hey'}
If you try to call one of the protected functions, an error occurs:
Traceback (most recent call last):
File "C:/Users/Lucas/PycharmProjects/testes/other.py", line 6, in <module>
t.__func_a()
AttributeError: Test instance has no attribute '__func_a'
Same thing if you try to access the protected environment variable:
Traceback (most recent call last):
File "C:/Users/Lucas/PycharmProjects/testes/other.py", line 5, in <module>
print t.__environment
AttributeError: Test instance has no attribute '__environment'
In my view this is the most elegant, simple and readable way to solve your problem, let me know if it fits your needs :)

Hook python module function

Basically I want to do something like this:
How can I hook a function in a python module?
but I want to call the old function after my own code.
like
import whatever
oldfunc = whatever.this_is_a_function
def this_is_a_function(parameter):
#my own code here
# and call original function back
oldfunc(parameter)
whatever.this_is_a_function = this_is_a_function
Is this possible?
I tried copy.copy, copy.deepcopy original function but it didn't work.
Something like this? It avoids using globals, which is generally a good thing.
import whatever
import functools
def prefix_function(function, prefunction):
#functools.wraps(function)
def run(*args, **kwargs):
prefunction(*args, **kwargs)
return function(*args, **kwargs)
return run
def this_is_a_function(parameter):
pass # Your own code here that will be run before
whatever.this_is_a_function = prefix_function(
whatever.this_is_a_function, this_is_a_function)
prefix_function is a function that takes two functions: function and prefunction. It returns a function that takes any parameters, and calls prefunction followed by function with the same parameters. The prefix_function function works for any callable, so you only need to program the prefixing code once for any other hooking you might need to do.
#functools.wraps makes it so that the docstring and name of the returned wrapper function is the same.
If you need this_is_a_function to call the old whatever.this_is_a_function with arguments different than what was passed to it, you could do something like this:
import whatever
import functools
def wrap_function(oldfunction, newfunction):
#functools.wraps(function)
def run(*args, **kwargs):
return newfunction(oldfunction, *args, **kwargs)
return run
def this_is_a_function(oldfunc, parameter):
# Do some processing or something to customize the parameters to pass
newparams = parameter * 2 # Example of a change to newparams
return oldfunc(newparams)
whatever.this_is_a_function = wrap_function(
whatever.this_is_a_function, this_is_a_function)
There is a problem that if whatever is a pure C module, it's typically impossible (or very difficult) to change its internals in the first place.
So, here's an example of monkey-patching the time function from the time module.
import time
old_time = time.time
def time():
print('It is today... but more specifically the time is:')
return old_time()
time.time = time
print time.time()
# Output:
# It is today... but more specifically the time is:
# 1456954003.2
However, if you are trying to do this to C code, you will most likely get an error like cannot overwrite attribute. In that case, you probably want to subclass the C module.
You may want to take a look at this question.
This is the perfect time to tout my super-simplistic Hooker
def hook(hookfunc, oldfunc):
def foo(*args, **kwargs):
hookfunc(*args, **kwargs)
return oldfunc(*args, **kwargs)
return foo
Incredibly simple. It will return a function that first runs the desired hook function (with the same parameters, mind you) and will then run the original function that you are hooking and return that original value. This also works to overwrite a class method. Say we have static method in a class.
class Foo:
#staticmethod
def bar(data):
for datum in data:
print(datum, end="") # assuming python3 for this
print()
But we want to print the length of the data before we print out its elements
def myNewFunction(data):
print("The length is {}.".format(len(data)))
And now we simple hook the function
Foo.bar(["a", "b", "c"])
# => a b c
Foo.bar = hook(Foo.bar, myNewFunction)
Foo.bar(["x", "y", "z"])
# => The length is 3.
# => x y z
Actually, you can replace the target function's func_code. The example below
# a normal function
def old_func():
print "i am old"
# a class method
class A(object):
def old_method(self):
print "i am old_method"
# a closure function
def make_closure(freevar1, freevar2):
def wrapper():
print "i am old_clofunc, freevars:", freevar1, freevar2
return wrapper
old_clofunc = make_closure('fv1', 'fv2')
# ===============================================
# the new function
def new_func(*args):
print "i am new, args:", args
# the new closure function
def make_closure2(freevar1, freevar2):
def wrapper():
print "i am new_clofunc, freevars:", freevar1, freevar2
return wrapper
new_clofunc = make_closure2('fv1', 'fv2')
# ===============================================
# hook normal function
old_func.func_code = new_func.func_code
# hook class method
A.old_method.im_func.func_code = new_func.func_code
# hook closure function
# Note: the closure function's `co_freevars` count should be equal
old_clofunc.func_code = new_clofunc.func_code
# ===============================================
# call the old
old_func()
A().old_method()
old_clofunc()
output:
i am new, args: ()
i am new, args: (<__main__.A object at 0x0000000004A5AC50>,)
i am new_clofunc, freevars: fv1 fv2

Call Nested Function in Python

I have a method that i have broken into smaller nested functions to break up the code base:
def foo(x,y):
def do_this(x,y):
pass
def do_that(x,y):
pass
do_this(x,y)
do_that(x,y)
return
Is there a way to run one of the nested functions by itself. eg:
foo.do_this(x,y)
EDIT:
I am trying to setup caching on a web server i have built using pyramid_breaker
def getThis(request):
def invalidate_data(getData,'long_term',search_term):
region_invalidate(getData,'long_term',search_term)
#cached_region('long_term')
def getData(search_term):
return response
search_term = request.matchdict['searchterm']
return getData(search_term)
This is my understanding may not be accurate:
Now the reason i have this is that the namespace used by the decorator to create the cache key is genereated from the function and the arguements. You can't therefore just put the decorator on getThis as the request variable is unique-ish and the cache is useless. So i created the inner function which has repeatable args (search_term).
However to invalidate the cache (ie refresh), the invalidation function requires scope to know of the 'getData' function so also needs to be nested. Therefore i need to call the nested function. You wonderful people have made it clear its not possible so is someone able to explain how i might do it with a different structure?
I assume do_this and do_that are actually dependent on some argument of foo, since otherwise you could just move them out of foo and call them directly.
I suggest reworking the whole thing as a class. Something like this:
class Foo(object):
def __init__(self, x, y):
self.x = x
self.y = y
def do_this(self):
pass
def do_that(self):
pass
def __call__(self):
self.do_this()
self.do_that()
foo = Foo(x, y)
foo()
foo.do_this()
These previous answers, telling you that you can not do this, are of course wrong.
This is python, you can do almost anything you want using some magic code magic.
We can take the first constant out of foo's function code, this will be the do_this function. We can then use this code to create a new function with it.
see https://docs.python.org/2/library/new.html for more info on new and https://docs.python.org/2/library/inspect.html for more info on how to get to internal code.
Warning: it's not because you CAN do this that you SHOULD do this,
rethinking the way you have your functions structured is the way to go, but if you want a quick and dirty hack that will probably break in the future, here you go:
import new
myfoo = new.function(foo.func_code.co_consts[1],{})
myfoo(x,y) # hooray we have a new function that does what I want
UPDATE: in python3 you can use the types module with foo.__code__:
import types
myfoo = types.FunctionType(foo.__code__.co_consts[1], {})
myfoo() # behaves like it is do_this()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: do_this() missing 2 required positional arguments: 'x' and 'y'
There is, you have to make them as an attribute of the function object. But this will work only after the first call of foo.
def foo(x,y):
def do_this(x,y):
pass
def do_that(x,y):
pass
do_this(x,y)
do_that(x,y)
foo.do_this = do_this
foo.do_that = do_that
return
>>> foo.do_this(1, 2)
AttributeError: 'function' object has no attribute 'do_this'
>>> foo(1, 2)
>>> foo.do_this(1, 2)
>>>
No (apart from poking around in closure objects, which is complete overkill here). If you need that, use a class.
class foo(object):
def do_this(self, x, y):
...
def do_that(self, x, y):
...
def do_other_stuff(self, x, y):
# or __call__, possibly
Or just put those functions in the outer scope, since you're passing everything as arguments anyway:
def foo(x, y):
do_this(x, y)
do_that(x, y)
def do_this(x, y):
...
def do_that(x, y):
...
No, there is not. Since you may access variables in an outer scope from within a nested function:
def foo(x,y):
def do_this(z):
print(x,y,z)
# ...
there is no way to call do_this while providing a binding for x and y.
If you must call do_this from elsewhere, simply make it a top level function at the same level as foo.
You can try this way:
def a(x, y):
name = 'Michael'
a.name = name
a.z = z = x * y
#a.z = z
def b():
def give_me_price(f,g):
price = f * g
return price
def two(j,k):
surname = 'Jordan' # without return surname give None
# two = two('arg1', 'arg2')
# b.blabla = two
one = give_me_price(5, 10)
b.halabala = one
print(a.name) # ;)
x = 20
y = 30
a(x,y) # IMPORTANT! first you must run function
print(a.z)
print(a.name * 5)
print('-'*12)
b() # IMPORTANT! first you must run function
print('price is: ' + str(b.give_me_price(5, 25)))
# print(b.blabla)
This is how I did it.
CODE
def getMessage(a="", b="", c=""):
def getErrorMessage(aa, bb):
return "Error Message with/without params: {}{}".format(aa, bb)
def getSuccessMessage(bb, cc):
return "Success Message with/without params: {}{}".format(bb, cc)
def getWarningMessage(aa, cc):
return "Warning Message with/without params: {}{}".format(aa, cc)
return {
"getErrorMessage": getErrorMessage(a, b),
"getSuccessMessage": getSuccessMessage(b, c),
"getWarningMessage": getWarningMessage(a, c),
}
a = "hello"
b = " World"
c = "!"
print(getMessage(a, b)["getErrorMessage"])
print(getMessage(b=b, c=c)["getSuccessMessage"])
print(getMessage(a=a, c=c)["getWarningMessage"])
print(getMessage(c=c)["getWarningMessage"])
OUTPUT
Error Message with/without params: hello World
Success Message with/without params: World!
Warning Message with/without params: hello!
Warning Message with/without params: !

Categories

Resources