- Notifications
You must be signed in to change notification settings - Fork23
czheo/syntax_sugar_python
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
This lib adds some anti-Pythonic "syntactic sugar" to Python.
NOTE: This is merely an experimental prototype to show some potential of operator overloading in Python. Only tested under Python 3.6.0. Anything may evolve without announcement in advance.
Inspired byhttps://github.com/matz/streem.
Also, you can watch the last part of this Matz's talk to understand the intuition behind this project.
pip install syntax_sugarTo test out this lib, you can simply do.
fromsyntax_sugarimport*
For serious use, you can explicitly import each component as explained below ... if you dare to use this lib.
fromsyntax_sugarimportpipe,ENDfromfunctoolsimportpartialpipe(10)|range|partial(map,lambdax:x**2)|list|print|END# put 10 into the pipe and just let data flow.# output: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]# remember to call END at the end# NOTE: everything in the middle of the pipe is just normal Python functionspipe(10)|range| (map,lambdax:x**2)|list|print|END# Tuples are shortcuts for partial functionsfromsyntax_sugarimporteachx=pipe(10)|range|each(lambdax:x**2)|END# We can also save the result in a variable.# `each` is an eager evaluated version of the partial function of `map`, which returns a list instead of a map object. (Equivalent to `map` in Python 2)pipe(10)|range|each(str)|''.join>'test.txt'# wanna write to a file? Why not!# write "0123456789" to test.txt# We don't need to put END here.
We can connect multiple pipes to create a longer pipe
fromsyntax_sugarimportpipe,each,ENDfromfunctoolsimportreducep1=pipe(10)|range|each(lambdax:x/2)# head pipe can have input valuep2=pipe()| (reduce,lambdaacc,x: (acc+x)/2)p3=pipe()|int|range|sum# middle pipes can have no input valuep1|p2|p3|END# returns 6p=p1|p2|p3p()# You can invoke the pipe by calling it as a function# you can also put a different value in the pipep(20)# returns 36
By default, pipe works with threads.
You can have a function running in a seperate thread with pipe. Just put it in a[] or more explicitlyt[]. Threads and processes are also available.
fromsyntax_sugarimport (thread_syntaxast,process_syntaxasp)pipe(10)| [print]|END# print run in a threadpipe(10)|t[print]|END# print run in a threadpipe(10)|p[print]|END# print run in a process
What makes this syntax good is that you can specify how many threads you want to spawn, by doing[function] * n wheren is the number of threads.
pipe([1,2,3,4,5])| [print]*3|END# print will run in a ThreadPool of size 3
Here is an example of requesting a list of urls in parallel
importrequests(pipe(['google','twitter','yahoo','facebook','github'])|each(lambdaname:'http://'+name+'.com')| [requests.get]*3# !! `requests.get` runs in a ThreadPool of size 3|each(lambdaresp: (resp.url,resp.headers.get('Server')))|list|END)# returns# [('http://www.google.com/', 'gws'),# ('https://twitter.com/', 'tsa_a'),# ('https://www.yahoo.com/', 'ATS'),# ('https://www.facebook.com/', None),# ('https://github.com/', 'GitHub.com')]
fromsyntax_sugarimportis_a,has,to,step,drop1/is_a/int# equivalent to `isinstance(1, int)`1/as_a/str# "1"range(10)/has/'__iter__'# equivalent to `hasattr(range(10), "__iter__")`1/to/10# An iterator similar to `range(1, 11)`.# Python's nasty range() is right-exclusive. This is right-inclusive.10/to/1# We can go backward.'0'/to/'9'# We can also have a range of characters :)1/to/10/step/2# We can also specify step sizes.# Similar to `range(1, 11, 2)`10/to/1/step/2# Go backward.# Similar to `range(10, 0, -2)`1/to/10/drop/5# there is a `drop` functon which drop N items from the head# An iterator similar to [6, 7, 8, 9, 10]
/to/ has some advanced features
- lazy evaluation.
- support infinity.
- support product operation.
- support pipe.
fromsyntax_sugarimportINF,take,each# CAUTION: this will infinitely print numbersforiin1/to/INF:print(i)1/to/INF/take/5/as_a/list# there is a `take` functon which is similar to itertools.islice# return [1, 2, 3, 4, 5]1/to/ .../take/5/as_a/list# ... is equivalent to INF0/to/-INF/step/2/take/5/as_a/list# also works with negative infinity.# return [0, -2, -4, -6, -8](1/to/3)* (4/to/6)/as_a/list# all combinations of [1..3] * [4..6]# return [(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]1/to/10/take/5|each(lambdax:x**2)|END# These infix functions can also be piped.# [1, 4, 9, 16, 25]
Make your own infix function, so you can append multiple items to a list in one line.
fromsyntax_sugarimportinfix@infixdefpush(lst,x):lst.append(x)returnlst[]/push/1/push/2/push/3# returns [1,2,3]
You can also do
defpush(lst,x):lst.append(x)returnlstipush=push/as_a/infix[]/ipush/1/ipush/2/ipush/3# returns [1,2,3]
In math,(f * g) (x) = f(g(x)). This is called function composition.
# lmap equivalent to `list(map(...))`lmap=compose(list,map)lmap(lambdax:x**2,range(10))
Let's say we want to representf * g * h in a program, i.e.fn(x) = f(g(h(x)))
f=lambdax:x**2+1g=lambdax:2*x-1h=lambdax:-2*x**3+3fn=compose(f,g,h)fn(5)# 245026
or you can do
f=composable(lambdax:x**2+1)g=composable(lambdax:2*x-1)h=composable(lambdax:-2*x**3+3)fn=f*g*hfn(5)# 245026
Sometimes you may prefer the decorator way.
# make your own composable functions@composabledefadd2(x):returnx+2@composabledefmul3(x):returnx*3@composabledefpow2(x):returnx**2fn=add2*mul3*pow2# equivalent to `add2(mul3(pow2(n)))`fn(5)# returns 5^2 * 3 + 2 = 77
More receipes:https://github.com/czheo/syntax_sugar_python/tree/master/recipes
About
A library adding some anti-Pythonic syntatic sugar to Python
Topics
Resources
Contributing
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.
Contributors5
Uh oh!
There was an error while loading.Please reload this page.
