Let's say I have the following definition:
def foo(x, y):
return x + y
And then I want to have a copy of the function foo (let's call it bar), where x is always equal to 0.
i.e. bar(4) would return 4.
How can I do this in Python?
Thanks!
Maybe like this:
bar = lambda y: foo (0, y)
If you want to delete foo, as user pointed out, you can use:
def foo (x, y): return x + y
bar = (lambda f: lambda y: f (0, y) ) (foo)
print (bar (4) )
del foo
print (bar (4) )
functools.partial is an efficient way to do this:
import functools
bar = functools.partial(foo, 0)
bar(4) == 4
It also lets you supply a function that isn't bound to a variable, or rebind the variable after creating the partial object, which can prevent errors with loops or comprehensions:
from operator import add, sub, mul
funcs = [lambda x: foo(3, x) for foo in add, sub, mul]
funcs[0](3) == 9 # Not 6!
funcs = [functools.partial(foo, 3) for foo in add, sub, mul]
funcs[0](3) == 6 # Works!
Related
How a function can be applied on top of another function like a(b)(x,y) where a and b are functions and x and y are arguments? Can somebody provide me with the term we call this concept along with some examples.
For a(b)(x, y) to make sense, a needs to be a function that takes b as an argument and produces a new function that takes two arguments. Here's an example:
>>> def a(func):
... def wrapped(x, y):
... return 2 * func(x, y)
... return wrapped
...
>>> def b(x, y):
... return x + y
...
>>> a(b)(1, 2)
6
In the above example a is a function that wraps a two-argument function and doubles its result. b(1, 2) is 3, and a(b)(1, 2) is therefore 6.
a function can be applied to another function like this
a(b)(x,y)
if the returned value from a(b) is a function that takes 2 arguments
in that case the function that is returned from a(b) will be applied on the parameters x,y
for example :
def mul(x,y):
return x*y
def add5_to_func(func):
return lambda x,y : func(x,y) + 5
print(add5_to_func(mul)(3,3)) # will print 14
I have the following straightforward function in Python 3:
def func(i,j):
return lambda i,j: (i*j)
Here's an example of what this function should do:
IN: func(4,'Hello')
OUT: ('Hello' 'Hello' 'Hello' 'Hello')
However, the actual output is an address in memory where the result is stored. What modification do I need to make?
If you want to return the value of i * j, then go ahead and return it. A lambda means it returns a function that acts as you want it to. Consider this:
def mul(x, y):
return x * y
def func(x, y):
return lambda x, y: x*y
Now let's take a look at a little shell session:
>>> mul(4, 'hello')
'hellohellohellohello'
>>> func(4, 'hello')
<function 'lambda' at ...>
>>> f = func(4, 'hello')
>>> f(4, 'hello')
'hellohellohellohello'
As you can see, when you use lambda, your function returns a function which, in turn, needs to be called. The arguments x and y have no correspondence to the arguments in the lambda function.
Since your expected output is a tuple of x lots of y, use a tuple in your function:
def func(i, j):
return (j,) * i
Is there a way to define a function which knows how many variables to return based on how many outputs the user expects?
Let me illustrate the idea. Assume the following function:
def function():
a = 1
b = 2
c = 3
return a, b, c
Then, I would like my function to behave like:
>>> x = function()
>>> x
1
>>> x, y = function()
>>> x
1
>>> y
2
>>> x, y, z = function()
>>> x
1
>>> y
2
>>> z
3
Is there a function or concept in python that can help me to achieve that? Maybe decorators?
Any idea is welcome!
PD: My level of Python is still very basic.
EDIT:
I am currently moving from IDL to Python. So I am missing the nice feature in IDL that you can actually choose to return as many variables as desired by doing like:
FUNCTION function, a=a, b=b, c=c
a=1
b=2
c=3
RETURN, a
And then you can simply ask what you want to get back
IDL> x=function()
IDL> print, x
1
IDL> x=function(y=b)
IDL> print, x
1
IDL> print, y
2
IDL> x=function(y=b, z=c)
IDL> print, x
1
IDL> print, y
2
IDL> print, c
3
Instead of returning different values, you could call it differently:
x, *_ = function()
x, y, *_ = function()
x, y, z, *_ = function() # *_ is optional here if it only returns 3 things
Doing this assigns all unused returned values to the _ variable, so if you want them to get gc'd early, you have to del _.
You can only ever return a single object. Note, your function is returning a tuple. However, Python supports syntax that lets you unpack variables flexibly
x,_,_ = function()
Or
x,y,_ = function()
Or even with extended unpacking:
x, *_ = function()
Note, using _ as a throwaway variable is merely a convention.
Short of insane tricks like examining your caller’s bytecode to see how many values it’s expecting, this is impossible: the interpreter will not accept any mismatched number of values (it checks for and traps extras).
While not as Pythonic as unpacking, you can create a decorator and specify the number of returned values that are allowed:
def filter_results(val):
def outer(f):
def wrapper(*args, **kwargs):
v = f(*args, **kwargs)[:val]
return v[0] if len(v) == 1 else v
return wrapper
return outer
#filter_results(1)
def function():
a = 1
b = 2
c = 3
return a, b, c
r = function()
Output:
1
Full results:
#filter_results(2)
def function():
...
x, y = function()
Lastly:
#filter_results(3)
def function():
...
x, y, z = function()
If I have the given dispatch-style function to represent a pair, how can I implement the same using a one-line lambda function?
# ADT Level 0 (dispatch-style pair)
def make_pair(x, y):
"""Dispatch-style pair"""
def dispatch(m):
if m == 0:
return x
elif m == 1:
return y
return dispatch
You could do something like:
make_pair = lambda x,y: lambda m: x if m == 0 else y if m == 1 else None
The outer lambda returns an (inner) lambda waiting for an argument m that returns the bound variables in the scope created by the outer.
>>>one_two = make_pair(1, 2)
>>>one_two(1)
2
>>> one_two(2)
>>>
You can use imbricated lambdas to return a lambda expression:
>>> make_pair=lambda x,y:lambda m:x if m==0 else y
>>> a=make_pair(2,4)
>>> a(1)
4
>>> a(0)
2
lambda m:x if m==0 else y is (more or less) equivalent to your dispatch function (a(2) will return 4 in my case)
I work in Python. Recently, I discovered a wonderful little package called fn. I've been using it for function composition.
For example, instead of:
baz(bar(foo(x))))
with fn, you can write:
(F() >> foo >> bar >> baz)(x) .
When I saw this, I immediately thought of Clojure:
(-> x foo bar baz) .
But notice how, in Clojure, the input is on the left. I wonder if this possible in python/fn.
You can't replicate the exact syntax, but you can make something similar:
def f(*args):
result = args[0]
for func in args[1:]:
result = func(result)
return result
Seems to work:
>>> f('a test', reversed, sorted, ''.join)
' aestt'
You can't get that exact syntax, although you can get something like F(x)(foo, bar, baz). Here's a simple example:
class F(object):
def __init__(self, arg):
self.arg = arg
def __call__(self, *funcs):
arg = self.arg
for f in funcs:
arg = f(arg)
return arg
def a(x):
return x+2
def b(x):
return x**2
def c(x):
return 3*x
>>> F(2)(a, b, c)
48
>>> F(2)(c, b, a)
38
This is a bit different from Blender's answer since it stores the argument, which can later be re-used with different functions.
This is sort of like the opposite of normal function application: instead of specifying the function up front and leaving some arguments to be specified later, you specify the argument and leave the function(s) to be specified later. It's an interesting toy but it's hard to think why you'd really want this.
If you want to use fn, with a little hack you can get a bit closer to Clojure syntax:
>>> def r(x): return lambda: x
>>> (F() >> r(x) >> foo >> bar >> baz)()
See how I added another function at the beginning of the composition chain that will just return x when called. The problem with this is that you still have to call your composed function, just without any arguments.
I think #Blender's answer is your best bet trying to emulate Clojure's thread function in Python.
I came up with this
def _composition(arg, *funcs_and_args):
"""
_composition(
[1,2,3],
(filter, lambda x: x % 2 == 1),
(map, lambda x: x+3)
)
#=> [4, 6]
"""
for func_and_args in funcs_and_args:
func, *b = func_and_args
arg = func(*b, arg)
return(arg)
This seems to work for simple input. Not sure it is worth the effort for complex input, e.g., ((42, 'spam'), {'spam': 42}).
def compose(function, *functions):
return function if not functions else \
lambda *args, **kwargs: function(compose(*functions)(*args, **kwargs))
def rcompose(*functions):
return compose(*reversed(functions))
def postfix(arg, *functions):
return rcompose(*functions)(arg)
Example:
>>> postfix(1, str, len, hex)
'0x1'
>>> postfix(1, hex, len)
3
My compose function that returns a function
def compose(*args):
length = len(args)
def _composeInner(lastResult, index):
if ((length - 1) < index):
return lastResult
return _composeInner(args[index](lastResult), index + 1)
return (lambda x: _composeInner(x, 0))
Usage:
fn = compose(
lambda x: x * 2,
lambda x: x + 2,
lambda x: x + 1,
lambda x: x / 3
)
result = fn(6) # -> 5
I understand what you mean. It doesn't make sense. In my opinion this python library
does it better.
>>> from compositions.compositions import Compose
>>> foo = Compose(lambda x:x)
>>> foo = Compose(lambda x:x**2)
>>> foo = Compose(lambda x:sin(x))
>>> (baz*bar*foo)(x)