- Notifications
You must be signed in to change notification settings - Fork146
A fancy and practical functional tools
License
Suor/funcy
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
A collection of fancy functional tools focused on practicality.
Inspired by clojure, underscore and my own abstractions. Keep reading to get an overvieworread the docs.Or jump directly tocheatsheet.
Works with Python 3.4+ and pypy3.
pip install funcy
Import stuff from funcy to make things happen:
fromfuncyimportwhatever,you,need
Merge collections of same type(works for dicts, sets, lists, tuples, iterators and even strings):
merge(coll1,coll2,coll3, ...)join(colls)merge_with(sum,dict1,dict2, ...)
Walk through collection, creating its transform (like map but preserves type):
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:
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:
take(4,iterate(double,1))# [1, 2, 4, 8]first(drop(3,count(10)))# 13lremove(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))# sameflatten(nested_structure)# flat iterdistinct('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:
partial(add,1)# inccurry(add)(1)(2)# 3compose(inc,double)(10)# 21complement(even)# oddall_fn(isa(int),even)# is_even_intone_third=rpartial(operator.div,3.0)has_suffix=rcurry(str.endswith,2)
Create decorators easily:
@decoratordeflog(call):print(call._func.__name__,call._args)returncall()
Abstract control flow:
walk_values(silent(int), {'a':'1','b':'no'})# => {'a': 1, 'b': None}@oncedefinitialize():"..."withsuppress(OSError):os.remove('some.file')@ignore(ErrorRateExceeded)@limit_error_rate(fails=5,timeout=60)@retry(tries=2,errors=(HttpError,ServiceDown))defsome_unreliable_action(...):"..."classMyUser(AbstractBaseUser):@cached_propertydefpublic_phones(self):returnself.phones.filter(public=True)
Ease debugging:
squares= {tap(x,'x'):tap(x*x,'x^2')forxin [3,4]}# x: 3# x^2: 9# ...@print_exitsdefsome_func(...):"..."@log_calls(log.info,errors=False)@log_errors(log.exception)defsome_suspicious_function(...):"..."withprint_durations('Creating models'):Model.objects.create(...)# ...# 10.2 ms in Creating models
Andmuch more.
Funcy is an embodiment of ideas I explain in several essays:
- Why Every Language Needs Its Underscore
- Functional Python Made Easy
- Abstracting Control Flow
- Painless Decorators
To run the tests using your default python:
pip install -r test_requirements.txtpy.test
To fully runtox
you need all the supported pythons to be installed. These are3.4+ and PyPy3. You can run it for particular environment even in absenseof all of the above:
tox -e py310tox -e pypy3tox -e lint
About
A fancy and practical functional tools