funcy

A fancy and practical functional tools

Latest version: 2.0 registry icon
Maintenance score
26
Safety score
100
Popularity score
75
Check your open source dependency risks. Get immediate insight about security, stability and licensing risks.
Security
  Vulnerabilities
Version Suggest Low Medium High Critical
2.0 0 0 0 0 0
1.18 0 0 0 0 0
1.17 0 0 0 0 0
1.16 0 0 0 0 0
1.15 0 0 0 0 0
1.14 0 0 0 0 0
1.13 0 0 0 0 0
1.12 0 0 0 0 0
1.11 0 0 0 0 0
1.10.3 0 0 0 0 0
1.10.2 0 0 0 0 0
1.10.1 0 0 0 0 0
1.10 0 0 0 0 0
1.9.1 0 0 0 0 0
1.9 0 0 0 0 0
1.8 0 0 0 0 0
1.7.5 0 0 0 0 0
1.7.4 0 0 0 0 0
1.7.3 0 0 0 0 0
1.7.2 0 0 0 0 0
1.7.1 0 0 0 0 0
1.7 0 0 0 0 0
1.6 0 0 0 0 0
1.5 0 0 0 0 0
1.4 0 0 0 0 0
1.3 0 0 0 0 0
1.2 0 0 0 0 0
1.1 0 0 0 0 0
1.0.0 0 0 0 0 0
0.10.1 0 0 0 0 0
0.10 0 0 0 0 0
0.9 0 0 0 0 0
0.8 0 0 0 0 0
0.7 0 0 0 0 0
0.6.0 0 0 0 0 0
0.5.6 0 0 0 0 0
0.5.4 0 0 0 0 0
0.5.3 0 0 0 0 0
0.5.2 0 0 0 0 0
0.5.1 0 0 0 0 0
0.5.0 0 0 0 0 0
0.4.1 0 0 0 0 0
0.4.0 0 0 0 0 0
0.3.4 0 0 0 0 0
0.3.3 0 0 0 0 0
0.3.2 0 0 0 0 0
0.3.1 0 0 0 0 0
0.3.0 0 0 0 0 0
0.2.1 0 0 0 0 0
0.2.0 0 0 0 0 0
0.1.0 0 0 0 0 0

Stability
Latest release:

2.0 - This version may not be safe as it has not been updated for a long time. Find out if your coding project uses this component and get notified of any reported security vulnerabilities with Meterian-X Open Source Security Platform

Licensing

Maintain your licence declarations and avoid unwanted licences to protect your IP the way you intended.

BSD   -   BSD License (Generic)

Is a wildcard

Not proprietary

OSI Compliant



Funcy |Build Status|

A collection of fancy functional tools focused on practicality.

Inspired by clojure, underscore and my own abstractions. Keep reading to get an overview or read the docs <https://funcy.readthedocs.io/>. Or jump directly to cheatsheet <https://funcy.readthedocs.io/en/stable/cheatsheet.html>.

Works with Python 3.4+ and pypy3.

Installation

::

pip install funcy

Overview

Import stuff from funcy to make things happen:

.. code:: python

from funcy import whatever, you, need

Merge collections of same type (works for dicts, sets, lists, tuples, iterators and even strings):

.. code:: python

merge(coll1, coll2, coll3, ...)
join(colls)
merge_with(sum, dict1, dict2, ...)

Walk through collection, creating its transform (like map but preserves type):

.. code:: python

walk(str.upper, {'a', 'b'})            # {'A', 'B'}
walk(reversed, {'a': 1, 'b': 2})       # {1: 'a', 2: 'b'}
walk_keys(double, {'a': 1, 'b': 2})    # {'aa': 1, 'bb': 2}
walk_values(inc, {'a': 1, 'b': 2})     # {'a': 2, 'b': 3}

Select a part of collection:

.. code:: python

select(even, {1,2,3,10,20})                  # {2,10,20}
select(r'^a', ('a','b','ab','ba'))           # ('a','ab')
select_keys(callable, {str: '', None: None}) # {str: ''}
compact({2, None, 1, 0})                     # {1,2}

Manipulate sequences:

.. code:: python

take(4, iterate(double, 1)) # [1, 2, 4, 8]
first(drop(3, count(10)))   # 13

lremove(even, [1, 2, 3])    # [1, 3]
lconcat([1, 2], [5, 6])     # [1, 2, 5, 6]
lcat(map(range, range(4)))  # [0, 0, 1, 0, 1, 2]
lmapcat(range, range(4))    # same
flatten(nested_structure)   # flat iter
distinct('abacbdd')         # iter('abcd')

lsplit(odd, range(5))       # ([1, 3], [0, 2, 4])
lsplit_at(2, range(5))      # ([0, 1], [2, 3, 4])
group_by(mod3, range(5))    # {0: [0, 3], 1: [1, 4], 2: [2]}

lpartition(2, range(5))     # [[0, 1], [2, 3]]
chunks(2, range(5))         # iter: [0, 1], [2, 3], [4]
pairwise(range(5))          # iter: [0, 1], [1, 2], ...

And functions:

.. code:: python

partial(add, 1)             # inc
curry(add)(1)(2)            # 3
compose(inc, double)(10)    # 21
complement(even)            # odd
all_fn(isa(int), even)      # is_even_int

one_third = rpartial(operator.div, 3.0)
has_suffix = rcurry(str.endswith, 2)

Create decorators easily:

.. code:: python

@decorator
def log(call):
    print(call._func.__name__, call._args)
    return call()

Abstract control flow:

.. code:: python

walk_values(silent(int), {'a': '1', 'b': 'no'})
# => {'a': 1, 'b': None}

@once
def initialize():
    "..."

with suppress(OSError):
    os.remove('some.file')

@ignore(ErrorRateExceeded)
@limit_error_rate(fails=5, timeout=60)
@retry(tries=2, errors=(HttpError, ServiceDown))
def some_unreliable_action(...):
    "..."

class MyUser(AbstractBaseUser):
    @cached_property
    def public_phones(self):
        return self.phones.filter(public=True)

Ease debugging:

.. code:: python

squares = {tap(x, 'x'): tap(x * x, 'x^2') for x in [3, 4]}
# x: 3
# x^2: 9
# ...

@print_exits
def some_func(...):
    "..."

@log_calls(log.info, errors=False)
@log_errors(log.exception)
def some_suspicious_function(...):
    "..."

with print_durations('Creating models'):
    Model.objects.create(...)
    # ...
# 10.2 ms in Creating models

And much more <https://funcy.readthedocs.io/>_.

Dive in

Funcy is an embodiment of ideas I explain in several essays:

  • Why Every Language Needs Its Underscore <https://suor.github.io/blog/2014/06/22/why-every-language-needs-its-underscore/>_
  • Functional Python Made Easy <https://suor.github.io/blog/2013/10/13/functional-python-made-easy/>_
  • Abstracting Control Flow <https://suor.github.io/blog/2013/10/08/abstracting-control-flow/>_
  • Painless Decorators <https://suor.github.io/blog/2013/11/03/painless-decorators/>_

Related Projects

Running tests

To run the tests using your default python:

::

pip install -r test_requirements.txt
pytest

To fully run tox you need all the supported pythons to be installed. These are 3.4+ and PyPy3. You can run it for particular environment even in absense of all of the above::

tox -e py310
tox -e pypy3
tox -e lint

.. |Build Status| image:: https://github.com/Suor/funcy/actions/workflows/test.yml/badge.svg :target: https://github.com/Suor/funcy/actions/workflows/test.yml?query=branch%3Amaster