6 ms·
The consensus here seems to be that Python is missing a pipe operator. That was one of the things I quickly learned to appreciate when transitioning from Mathem
by aquafox 1y ago
The consensus here seems to be that Python is missing a pipe operator. That was one of the things I quickly learned to appreciate when transitioning from Mathematica to R. It makes writing data science code, where the data are transformed by a series of different steps, so much more readable and intuitive.
I know that Python is used for many more things than just data science, so I'd love to hear if in these other contexts, a pipe would also make sense. Just trying to understand why the pipe hasn't made it into Python already.
- nxpnsv 1y agoI don't know if result = (df .pipe(fun1, arg1=1) .pipe(fun2, arg2=2) ) is much less readable than result <- df |> fun1(., arg1=1) |> fun2(., arg2=2) but I guess the R thing also works beyond dataframes which is pretty cool
- mb7733 1y agoI haven't used R in forever, but is your `.` placeholder actually necessary? From my recollection of pipe operator the value being pipe piped is automatically as the first argument to the next function. That may have been a different implementation of a pipe operator though.
- nxpnsv 1y agoProbably not, I didn’t use R much during the last decade …
- itishappy 1y agoThe pipe operator uses what comes before as the first argument of the function. This means in R it would be: result <- df |> fun1(arg1=1) |> fun2(arg2=2) Python doesn't have a pipe operator, but if it did it would have similar syntax: result = df |> fun1(arg1=1) |> fun2(arg2=2) In existing Python, this might look something like: result = pipe(df, [ (fun1, 1), (fun2, 2) ]) (Implementing `pipe` would be fun, but I'll leave it as an exercise for the reader.) Edit: Realized my last example won't work with named arguments like you've given. You'd need a function for that, which start looking awful similar to what you've written: result = pipe(df, [ step(fun1, arg1=1), step(fun2, arg2=2) ])
- Izkata 1y agoPython supports a syntax like your first example by implementing the appropriate magic method for the desired operator and starting the chain with that special object. For example, using just a single pipe: https://flexiple.com/python/python-pipeline-operator https://flexiple.com/python/python-pipeline-operator The functions with extra arguments could be curried, or done ad-hoc like lambda v: fun1(v, arg1=1)
- superbatfish 1y ago>Implementing `pipe` would be fun, but I'll leave it as an exercise for the reader. I like exercise: https://gist.github.com/stuarteberg/6bcbe3feb7fba4dc2574a989f196ee11 https://gist.github.com/stuarteberg/6bcbe3feb7fba4dc2574a989...
- nxpnsv 1y agoNeat!
- nxpnsv 1y agoThanks!
- lsaferite 1y agoI find this (hypothetical) syntax *very* elegant. result = df |> fun1(arg1=1) |> fun2(arg2=2)
- levocardia 1y agoThe pipe operator in R (really, tidyverse R, which might as well be its own language) is one of its "killer apps" for me. Working with data is so, so pleasant and easy. I remember a textbook that showed two ways of "coding" a cookie recipe: bake(divide(add(knead(mix(flour, water, sugar, butter)),eggs),12),450,12) versus mix(flour, water, sugar, butter) %>% knead() %>% add(eggs) %>% divide(12) %>% bake(temp=450, minutes=12) So much easier!
- hagendaasalpine 1y agopandas and polars both have pipe methods available on dataframes. you can method chain to the same effect. it's considered best practise in pandas as you're hopefully not mutating the initial df
- yccs27 1y agoYou'd never write that ugly one-liner. Just write the recipe imperatively: dough = mix(flour, water, sugar, butter) dough.knead() dough = dough.add(eggs) cookies = dough.divide(12) cookies = bake(temp=450, minutes=12) Might be more verbose, but definitely readable.
- aredox 1y agoMeh, it is really annoying to define all those brarely-used variables (and pray you don't have more than one kind of "dough" in your program... Otherwise you begin to have cookie_dough/CookieDough/cookie-dough/cookieDough and friends everywhere, and refactors begin to become annoying fast)
- atq2119 1y agoThe next step after pipe operators would be reverse assignment statements to capture the results. I find myself increasingly frustrated at seeing code like 'let foo = many lines of code'. Let me write something like 'many lines of code =: foo'.
- teo_zero 1y ago> reverse assignment statements to capture the results Interesting idea! However, I'm not sure I would prefer "Mix water, flour [...] and finally you'll get a pie" to "To make a pie: mix water, flour [...]"
- redochre 1y agoR does have a right assign operator, namely -> It's use is discourages in most style guides. I do not use it in scripts, but I use it heavily in console/terminal workflows where I'm experimenting. df |> filter() |> summarise() -> x x |> mutate() -> y plot(y)
- tekknik 1y agoIt seem like creative use of the map function and some iterators would provide the same functionality as a pipe does