Passing uncertain amount of inputs to one function's sub-functions - python

Sorry if I did not explain myself clearly.
I would like to create a wrapper to call pre-defined functions with different number of inputs. Of course, I can create an individual wrapper for each function, but I am wondering if there is a way to create a generic wrapper for all cases.
The functions that should be called are named 'fun1' and 'fun2' with different number of inputs. I need to create a wrapper 'fun_wrap(func_name, uncertain amount of inputs)', which only needs the function name to be called and its associated amount of inputs.
One more thing, I need to change the input names by adding '_in' and make them global variables first. Below is my broken code. Thanks for any suggestions!
def fun1(a,b):
return a+b
def fun2(a,b,c):
return a*b/c
def set_globals(**kwargs):
for argname in kwargs:
globals()['%s_in' % argname] = kwargs[argname]
def fun_wrap(func_name, uncertain amount of inputs):
ffunc_name(set_globals(uncertain amount of inputs))
In this way, if I can call final_fun with arguments like:
fun_wrap(fun1,a,b)
fun_wrap(fun2,a,b)
UPDATE
I tried to use *arg, but failed...
def fun1(a,b):
return a+b
def fun2(a,b,c):
return a*b/c
def set_globals(**kwargs):
for argname in kwargs:
globals()['%s_in' % argname] = kwargs[argname]
def fun_wrap(func_name, *arg):
func_name(set_globals(*arg))
fun_wrap(fun2,a=1,b=2,c=3)
got error:
Traceback (most recent call last):
File "D:\Dropbox\AppPest\rice\try.py", line 19, in <module>
fun_wrap(fun2,a=1,b=2,c=3)
TypeError: fun_wrap() got an unexpected keyword argument 'a'

def fun1(a,b):
return a + b
def fun2(a,b,c):
return a * b / c
def set_globals(**kwargs):
for argname in kwargs:
globals()['%s_in' % argname] = kwargs[argname]
def fun_wrap(func, **kwargs):
set_globals(**kwargs) # made the call to set_globals before calling your function
return func(**kwargs) # return the value returned by the functions called

Related

Python, How to use the # in class method

I try to use the # in the class method. like this
class Dataset:
#parse_func
def get_next_batch(self):
return self.generator.__next__()
and the parse function like this:
def parse_func(load_batch):
def wrapper(**para):
batch_files_path, batch_masks_path, batch_label = load_batch(**para)
batch_images = []
batch_masks = []
for (file_path, mask_path) in zip(batch_files_path, batch_masks_path):
image = cv2.imread(file_path)
mask = cv2.imread(mask_path)
batch_images.append(image)
batch_masks.append(mask)
return np.asarray(batch_images, np.float32), np.asarray(batch_masks, np.uint8), batch_label
return wrapper
However, when I call dataset.get_next_batch(), it will raise a exception as followed.
Traceback (most recent call last):
TypeError: wrapper() takes exactly 0 arguments (1 given)
Do you know why raise this error and any solution? Thank you very much!
The function wrapper(**kwargs) accepts named arguments only. However, in instance methods, the self is automatically passed as the first positional argument. Since your method does not accept positional arguments, it fails.
You could edit to wrapper(self, **kwargs) or, more general wrapper(*args, **kwargs). However, the way you are using it, it is not clear what those arguments are.
Just simply change
def parse_func(load_batch):
def wrapper(*para):
batch_files_path, batch_masks_path, batch_label = load_batch(*para)
batch_images = []
batch_masks = []
for (file_path, mask_path) in zip(batch_files_path, batch_masks_path):
image = cv2.imread(file_path)
mask = cv2.imread(mask_path)
batch_images.append(image)
batch_masks.append(mask)
return np.asarray(batch_images, np.float32), np.asarray(batch_masks, np.uint8), batch_label
return wrapper()
# symbol mean a decorator function. Here, it means parse_func(get_next_batch). So if the wrapper using the keyword params (**para), you just want to pass some params to the wrapper but you don't actually except for the self args. So here I replace the params to positional params *para.

call 2 functions in a function [duplicate]

This question already has answers here:
Assign multiple functions to a single variable?
(3 answers)
Closed 6 years ago.
The problem is as follows below:
Write a function compose that takes two functions as argument, we call them Fa and Fb, and returns a function, Fres, that means that outdata from the other function is indata to the first, ex: Fres(x) = Fa(Fb(x)).
run example:
>>> def multiply_five(n):
... return n * 5
...
>>> def add_ten(x):
... return x + 10
...
>>> composition = compose(multiply_five, add_ten)
>>> composition(3)
65
>>> another_composition = compose(add_ten, multiply_five)
>>> another_composition(3)
25
So as I understand this if I send in 3 the function compose will take 3+10 = 13
after that send that result into the multiply function it will do: 13*5 witch is 65.
this is the code I've written so far:
def multiply_five(n):
return n*5
def add_ten(x):
return x+10
def compose(func1, func2):
def comp(arg):
return func2(arg)
return func1(comp(arg))
I get compile error, and I've tried some different approaches:
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
composition = compose(multiply_five, add_ten)
File "C:\Users\Jim\Desktop\tdp002\5h.py", line 10, in compose
return func1(comp(arg))
NameError: name 'arg' is not defined
You don't want to call either func1 or func2 yet; you just want to return a function that will call them both.
def compose(func1, func2):
def _(*args, **kw):
return func1(func2(*args, **kw))
return _
You could also just use a lambda expression to create the composed function.
def compose(func1, func2):
return lambda *args, **kw: func1(func2(*args, **kw))
Try this:
def compose(func1, func2):
def comp(arg):
return func1(func2(arg))
return comp

Def return in class as second, third argument for Class

I am creating a class to make some calculations. The class would have 3 arguments to get started. I have done like this in a simplified representation:
class TheCalcs:
def __init__(self, pk_from_db, cat_score_list, final_score):
self.pk_from_db = pk_from_db
self.cat_score_list = cat_score_list
self.final_score = final_score
def calculate_cat_score(self):
#Do some calcs with the data of the pk_from_db and return that!
a_list_of_scores = [] # create a list of scores
return a_list_of_scores
def final_score(self): # The argument for this function would be the return of the calculate_cat_score function!
# Again do some calcs and return the final score
the_final_score = int()
return the_final_score
def score_grade(self): # the argument this this function again the return but now from the final_score function
# Do some cals and return the grade
the_grade = ("a string", "an integer")
return the_grade
When I call the class I would have to present the arguments --> However as you can see I just do now the value of the first argument. The second and the third being calculated throughout the class. When I call the class just with one argument I will of course have an error of failing arguments. Anyone has an idea on that?
If those values are calculated, simply don't make them arguments. You could instead call those calculation methods to compute the values:
class TheCalcs:
def __init__(self, pk_from_db):
self.pk_from_db = pk_from_db
self.cat_score_list = self.calculate_cat_score()
self.final_score = self.calculate_final_score()
# ...
or postpone calculations until you need them.

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