Import path for decorator-wrapped function? - python

Assuming I have a decorator and a wrapped function like this:
def squared(method):
def wrapper(x, y):
return method(x*x, y*y)
return wrapper
#squared
def sum(x, y):
return x+y
I have other code that would like to call the undecorated version of the sum function. Is there an import trick that can get me to this unwrapped method? If my code says from some.module.path import sum then, I get the wrapped version of the sum method, which is not what I want in this case. (Yes, I know I could break this out into a helper method, but that breaks some of the cleanliness of the pattern I'm going for here.)
I'm okay with adding extra "magic" to the decorator to provide some alternate symbol name (like orig_sum) that I could then import, I just don't know how to do that.

def unwrap(fn):
return fn.__wrapped__
def squared(method):
def wrapper(x, y):
return method(x*x, y*y)
wrapper.__wrapped__ = method
return wrapper
#squared
def sum(x, y):
return x+y
sum(2,3) -> 13
unwrap(sum)(2,3) -> 5

What about this?
def squared(method):
def wrapper(x, y):
return method(x*x, y*y)
return wrapper
def sum(x, y):
return x+y
squared_sum = squared(sum)
It's still a decorator, but you still can import squared and sum without any magic. Not sure if that's what you meant by 'helper method', but I find this much cleaner than a sum method, which actually sums the squares of its inputs.

Related

How to pass function as variable with fixed argument

I'm newbie in Python, but the second time I encouter this problem.
Problem:
In some libraries there are functions with arguments. Sometimes there is argument as function, like this:
def somefun(fun):
x = [1,2,3]
z = fun(x)
return z
And I want to pass there some other function like this:
def func(x,y):
return x*y
which have more than one argument. I want to make one argument static, so somefun except func as argument.
Finally I want to make some kind of cycle where I can change static arg.
Something like this:
for i in xrange(1,9):
somefun(func(i,*))
Please do not offer me to change any functions. They are from library and it's not very comfortable to change them.
Thanks a lot!
You can use lambda statement:
somefun(lambda x: func(i, x))
It sure sounds like you are looking for functools.partial. From the docs:
functools.partial(func, *args, **keywords)
Return a new partial object which when called will behave like func called with the positional arguments args and keyword arguments keywords.
In your example, you could pass partial(func, 10) as the argument to somefun. Or you could create the partial objects and use them in a loop:
for i in xrange(1,9):
somefun(partial(func, i))
My solution with decorator
from functools import wraps
import numpy as np
def p_decorate(f):
#wraps(f)
def wrapped(*args):
z = f(*args)
return z
return wrapped
#p_decorate
def myfunc(a,b):
"""My new function"""
z = np.dot(a,b)
return z
x = [1,2,3]
y = [4,2,0]
r = myfunc(x,y)
print (r)
print (myfunc.__name__)
print (myfunc.__doc__)
You can change myfunc as you wish.You can also insert more function layers.Without the use of this decorator factory,you would lose the name of myfunc and the docstring.

How to decorate a function while adding variables in Python

I'm trying to construct a decorator in Python where I add a variable at the decoration stage. I know how to write a decorator where I simply run a function on the results of another function, but I'm having trouble with the syntax of adding an additional variable. Essentially, I want to take this dot product function:
def dot(x,y):
temp1=[]
for i in range(len(x)):
temp1.append(float(x[i])*y[i])
tempdot=sum(temp1)
return tempdot
and subtract the value 'b' from the result, all in one larger function given parameters x,y,b
Am I trying to misuse the decoration functionality in this case? Thanks.
import functools
def subtracter(b):
def wrapped(func):
#functools.wraps(func)
def decorated_func(*args, **kwargs):
return func(*args, **kwargs) - b
return decorated_func
return wrapped
Then use it as
#subtracter(b=5)
def dot(x,y):
temp1=[]
for i in range(len(x)):
temp1.append(float(x[i])*y[i])
tempdot=sum(temp1)
return tempdot
By the way your dot function can be shorted with a generator expression like so:
def dot(x, y):
return sum(float(x)*y for x, y in zip(x, y))

How to construct such a functional-programming tool in Python?

I want a function named times(), in order to make:
times(func,2) equivalent to lambda x:func(func(x))
and times(func,5) equivalent to lambda x:func(func(func(func(func(x)))))
Is there such a tool in Python? What would the code looks like if I want to write it by myself?
Thanks!
I'd suggest to call this power(), since this is actually the nth power of a function. There is no such thing in the standard library, but you can easily implement it yourself:
def power(f, n):
def wrapped(x):
for i in range(n):
x = f(x)
return x
return wrapped
Thanks, Sven
I found a recursive way to do that, but yours looks more pythonic:
def power(func, n):
def lazy(x, i=n):
return func(lazy(x, i-1)) if i > 0 else x
return lazy
>>> power(lambda x:x*2,3)(9)
72
>>> power(lambda x:x*2,2)(9)
36
>>> power(lambda x:x*2,1)(9)
18
>>> power(lambda x:x*2,0)(9)
9
And a way implemented with decorator:
def powerize(n):
def wrapped(func):
def newfunc(*args):
return power(func,n)(*args)
return newfunc
return wrapped
#powerize(3)
def double_3(x):
return x*2
>>> double_3(8)
64

product of two functions

I have two functions, f and g. Both have the same signature: (x). I want to create a new function, z, with the same signature:
def z(x):
return f(x) * g(x)
except that I'd like to be able to write
z = f * g instead of the above code. Is it possible?
Something close is possible:
z = lambda x: f(x) * g(x)
Personally, I find this way more intuitive than z = f * g, because mathematically, multiplying functions doesn't mean anything. Depending on the interpretation of the * operator, it may mean composition so z(x) = f(g(x)), but definitely not multiplication of the results of invocation. On the other hand, the lambda above is very explicit, and frankly requires just a bit more characters to write.
Update: Kudos to JBernardo for hacking it together. I was imagining it would be much more hacky than in turned out. Still, I would advise against using this in real code.
The funny thing is that it is quite possible. I made a project some days ago to do things like that.
Here it is: FuncBuilder
By now you can only define variables, but you can use my metaclass with the help of some other functions to build a class to what you want.
Problems:
It's slow
It's really slow
You think you want that but describing functions the way they meant to be described is the right way.
You should use your first code.
Just as a proof of concept:
from funcbuilder import OperatorMachinery
class FuncOperations(metaclass=OperatorMachinery):
def __init__(self, function):
self.func = function
def __call__(self, *args, **kwargs):
return self.func(*args, **kwargs)
def func(self, *n, oper=None):
if not n:
return type(self)(lambda x: oper(self.func(x)))
return type(self)(lambda x: oper(self.func(x), n[0](x)))
FuncOperations.apply_operators([func, func])
Now you can code like that:
#FuncOperations
def f(x):
return x + 1
#FuncOperations
def g(x):
return x + 2
And the desired behavior is:
>>> z = f * g
>>> z(3)
20
I added a better version of it on the FuncBuilder project. It works with any operation between a FuncOperation object and another callable. Also works on unary operations. :D
You can play with it to make functions like:
z = -f + g * h
I can be done with the exact syntax you intended (though using lambda might be better), by using a decorator. As stated, functions don't have operators defined for them, but objects can be made to be callable just like functions in Python --
So the decorator bellow just wraps the function in an object for which the multiplication for another function is defined:
class multipliable(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kw):
return self.func(*args, **kw)
def __mul__(self, other):
#multipliable
def new_func(*args, **kw):
return self.func(*args, **kw) * other(*args, **kw)
return new_func
#multipliable
def x():
return 2
(tested in Python 2 and Python 3)
def y():
return 3
z = x * y
z()

Creating Python function with partial parameters

I want to pass a Python function to another function with some of its parameters "filled out" ahead of time.
This is simplification what I am doing:
def add(x, y):
return x + y
def increment_factory(i): # create a function that increments by i
return (lambda y: add(i, y))
inc2 = increment_factory(2)
print inc2(3) # prints 5
I don't want to use some sort of passing of args and later exploding it with *args because the function I am passing inc2 into doesn't know to pass args to it.
This feels a bit too clever for a group project... is there a more straightforward or pythonic way to do this?
Thanks!
This is called currying, or partial application. You can use the built-in functools.partial(). Something like the following would do what you want.
import functools
def add(x,y):
return x + y
inc2 = functools.partial(add, 2)
print inc2(3)
You could also accomplish the same with a lambda function:
inc2 = lambda y: add(2, y)
print inc2(3)

Categories

Resources