Creating Python function with partial parameters - python

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)

Related

iterating through a function's sub functions python

The goal is to try and access any function's sub functions. I've looked around and I'm not too sure there is a way to do it. When I've tried using
functions = [name for name, obj in inspect.getmembers(sys.modules[__name__], inspect.isfunction)]
which returns the functions in some module (in the above __name__==__main__). When I have used that method, it doesn't return any sub functions. However I'd like to access sub functions that look something like
def f(x):
def y(x):
return x += 3
def z(x):
return x**2 - 1
x += y(x)
x += z(x)
return x
So it seems to me like there should be some way to access them with a magic method of f or some attribute of f. I have a hard time believing that those sub functions aren't stored as some attribute of f, but I have no idea.
In the end, what I need to do is to iterate through the sub functions of some function, so I thought the solution would look something like
for subfunc in f.__method_that_returns_subfuncs__():
if 'my_string' == subfunc.__name__:
out = subfunc(args)
I just need to be able to compare a string to a subfunction name then call that subfunction.
Thanks
There's no implicit list of functions to iterate over. You need to define it yourself. Simply functions can be assigned directly to a list by defining them with lambda expressions; more complex functions will need to be defined first, then added. Examples of each:
def f(x):
funcs = []
def y(x):
return x += 3
f.append(y)
f.append(lambda x: x**2 - 1)
for func in funcs:
x = func(x)
return x
If you care about the name, you can access it via the function object's __name__ attribute.
for func in funcs:
if func.__name__ == "some_func":
x = func(x)

Python Lambda function variable ordering

If I state a lambda function like this:
someLambdaFunction = lambda x,y: x+x**2+y
can I reverse the ordering of that lambda to say
someOtherLambdaFunction = lambda y,x: x+x**2+y
without rewriting the whole lambda function? Just switch the arguments?
Yes, you can do something like this:
someLambdaFunction = lambda x,y: x+x**2+y
someOtherLambdaFunction = lambda y, x: someLambdaFunction(x, y)
Basically, reuse the original someLambdaFunction
You can write a general function that swaps the first two arguments of another function:
def swap2(func):
""" Swap the first two arguments of a function """
def wrapped(x, y, *args, **kwargs):
return func(y, x, *args, **kwargs)
return wrapped
f = lambda x,y: x+x**2+y
f_swapped= swap2(f)
assert f(3, 4) == f_swapped(4, 3)
This works because functions are just regular Python objects, that can be passed around just like integers, strings, etc.
By the way, there is almost never a reason to write something = lambda .... Use def something(...) instead.

Python - Pass default values for arguments that are function of other arguments of the function

I would like to write a function in which the default value of one argument is a function of some arguments that are being passed to the same function. Something like this:
def function(x, y = function2(x)):
##definition of the function
Is it possible to write such a function in Python?
I came across this answer for c++. But there is no method overloading in Python
Thanks in advance.
A pretty usual way of solving this is by using None as a placeholder:
def function(x, y=None):
if y is None:
y = f2(x)
pass # whatever function() needs to do
This makes no sense. hat are you trying to achieve? What is the Y? Is taht function? then you must write:
def function(x, y = function2):
##definition of the function
If the Y is a simple value then you must write:
def function(x, y = None):
if y is None:
y = function2(x)
I don't know what exactly are you trying to achieve here use case wise but you can use a decorator that does what is required for you.
A silly example is here https://repl.it/#SiddharthShishu/IntrepidPunctualProspect
def function(x, y=None):
if y is None:
y = f2(x)

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.

lambda in python

I'm revisiting some scheme excercises in python (if that makes sense) to find out what python can do in terms of FP. My problem concerns lambda in python :
Can i define a general function in python with an operator as one of the arguments?
Think this :
def f (op,x,y):
#return some lambda function that combines x and y in the appropriate way
#i.e if op is +, then return x+y, if op is -, then return x-y etc
#Edit : added usage
#this should be called like this:
f(+, 1,2) #should return 3
I know this is possible in scheme, but is there something equivalent in python? I've gotten the impression that lambda in python is just a shorter way of defining a method, and I've not found any way to define a general combiner function in python.
I can see some points in your question, lets go through them in order:
1. Can I pass a function as a parameter to someone?
Yes:
def f(op, x, y):
return op(x, y)
def add(x, y):
return x + y
f(add, 10, 7) #gives 17
2. What about operators then?
Unlike scheme, Python operators are not functions so you can't pass them directly as parameters. You can either create the wrapper functions yourself or you can import the operator module from the standard library.
import operator
operator.add(1, 2)
(lambda x,y : x+y)(1, 2)
Operators not being real functions is a little sad in most cases but at least Python gives us chained comparisons like 10 <= x < 100 in exchange...
3. So what is the difference between Python and Scheme then?
In the general sense, functions in Python are as powerful as functions in Scheme, however there are some things to note:
The lambda keyword is limited
You can only have a single expression as the function body
f = lambda x, y: x + y
Since there are a bunch of things in Python that are statements and not expressions (assignments, the 2.x print, ...), you often need to fall back to named functions instead.
There are closures
def make_printer(msg):
def printer():
print msg
return printer
printer('a message')()
But mutating variables in them is a pain
This doesn't work. It tries to bind a new n for the inner function instead of using the outer one
def make_counter(n):
def inc():
n = n + 1
return n
return inc
new 3.x nonlocal keyword
def make_counter(n):
def inc():
nonlocal n
n = n + 1
return n
return inc
workaround w/ mutable objects
def make_counter(n):
nw = [n]
def inc():
nw[0] = nw[0] + 1
return nw[0]
return inc
Objects instead of closures. Uses the magic __call__ method to pretend its a function
class Counter:
def __init__(self, n):
self.n = n
def __call__(self):
self.n += 1
return self.n
Operators aren't really function in python, more like methods -- x + y is short for x.__add__(y), or y.__radd__(x). You can use the functions in the operator module to emulate the behavior you want.
I think your best bet is to make a function that does the operator, and pass that:
def f(op, x, y):
return op(x, y)
f(lambda x, y: x + y, 1, 2)
Looks a little redundant though when you can do:
f = lambda x, y: x + y
f(1, 2)
You cannot syntactically pass an operator in python. E.g. f(+) is a syntax error. However, if you consider op to be any function, you can use def or lambda:
def f(op, x, y):
def op_func():
return op(x, y)
return op_func
or
def f(op, x, y):
op_func = lambda: op(x, y)
return op_func
In your case, you wish to evaluate the function:
def f(op, x, y):
return op(x, y)
Remember that Python is interpreted, so even def statements are evaluated at runtime.
[ If for some reason you need to, you can access the built-in operators as functions using the operator module: http://docs.python.org/library/operator.html ]
Check operator module. All python operators are available there in the form of functions.
example:
import operator
operate = lambda op, x, y: op(x, y)
operate(operator.add, 1, 2)

Categories

Resources