Skip to content

Instantly share code, notes, and snippets.

@ieure
Created September 14, 2009 20:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ieure/186905 to your computer and use it in GitHub Desktop.
Save ieure/186905 to your computer and use it in GitHub Desktop.
Functional version of the Python */** operators
# -*- coding: utf-8 -*-
#
# Author: Ian Eure <ian@digg.com>
#
"""Star function."""
from functools import partial
import unittest
def star(f, *args, **kwargs):
"""Return a function which works like the * operator.
This is a mix of partial application and the * / ** operator
(e.g. apply). When called with a function and arguments, returns a
function with arguments partially applied, which accepts further
arguments supplied in a sequence, dict, or both.
e.g.
star(f, 1, 2)() -> f(1, 2)
star(f, 1)((2, 3)) -> f(1, 2 ,3)
star(f)((1, 2)) -> f(1,2)
star(f)({'a': 1, 'b':2}) = f(a=1, b=2)
If you supply one non-sequence argument, it will do the right thing:
star(f, 1)(2) -> f(1, 2)
It's useful for applying dicts or sequences as function arguments:
map(star(f), {'a': 1, 'b': 2}.items()) -> (f(a=1), f(b=2))
"""
f = partial(f, *args, **kwargs)
def __inner__(args = None, kwargs = None):
if isinstance(args, dict):
_kwargs = args
if kwargs:
_kwargs.update(kwargs)
kwargs = None
kwargs = _kwargs
args = None
if args != None and not \
(isinstance(args, tuple) or isinstance(args, list)):
args = (args,)
args = args or ()
kwargs = kwargs or {}
return f(*args, **kwargs)
return __inner__
def _bar(a, b, c=None):
if c:
return "%s%s%s" % (a, b, c)
return "%s%s" % (a, b)
class TestStar(unittest.TestCase):
def _foo(self, a, b, c=None):
return _bar(a, b, c)
def test_star_plain(self):
for f in (self._foo, _bar):
f_ = star(f)
self.assert_(f_((1, 2)) == "12")
f_ = star(f, 1)
self.assert_(f_((2,)) == "12")
f_ = star(f, 1, 2)
self.assert_(f_({'c': 3}) == "123")
f_ = star(f, 1)
self.assert_(f_(2) == "12")
if __name__ == '__main__':
unittest.main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment