# Piping is Method Chaining

What `R` users now call piping, popularized by Stefan Milton Bache and Hadley Wickham, is inline function application (this is notationally similar to, but distinct from the powerful interprocess communication and concurrency tool introduced to Unix by Douglas McIlroy in 1973). In object oriented languages this sort of notation for function application has been called “method chaining” since the days of `Smalltalk` (~1972). Let’s take a look at method chaining in `Python`, in terms of pipe notation.

Let’s work an example using `Python`‘s `Pandas` package (and classes).

``import pandas as pd``
``````data = [['alpha', 'a', 1, 0],
['beta', 'b', 2, 10],
['gamma', 'b', 3, 10]]
df = pd.DataFrame(data,
columns=['name', 'group', 'value', 'cost'])
print(df)``````
``````    name group  value  cost
0  alpha     a      1     0
1   beta     b      2    10
2  gamma     b      3    10``````

Method chaining is when methods return a reference to their host-object (or reference to a replacement for their host-object). This lets us call a sequence of methods one after the other as we show below.

``print(df.groupby("group").agg({"value":["max", "min"], "cost":["mean"]}))``
``````      value     cost
max min mean
group
a         1   1    0
b         3   2   10``````

This may not be considered legible (especially as it was combined with `print()` function notation), so we use a common notation convention and insert a line-break before each method dispatch “`.`“. The parenthesis surrounding the whole expression are a common `Python` convention to facilitate multi-line expressions.

``````(
df
.groupby("group")
.agg({"value":["max", "min"], "cost":["mean"]})
.pipe(print)
)``````
``````      value     cost
max min mean
group
a         1   1    0
b         3   2   10``````

Or, to emphasize the similarity to pipes, we can use another convention (that contravenes the PEP8 style guide): end the lines with `.` which is the method dispatch “`.`” symbol plus a line continuation mark.

``````df .
groupby("group") .
agg({"value":["max", "min"], "cost":["mean"]}) .
pipe(print)``````
``````      value     cost
max min mean
group
a         1   1    0
b         3   2   10``````

The above is just as with the `Bizarro Pipe` in `R`: the pipe is available as a convention over the existing language syntax. In `Python` (for method chaining enabled classes and methods) the glyph “`.`” is in fact already a method application operator or pipe (as is the glyph “`.EOL`“, where `EOL` denotes the line-break or end of line). With method-chaining conventions the “`.`” already is “a pipe” organizing method application form left to right without the need for illegible nesting. In `R` the glyph “`->.;`” is a function application operator or pipe (which we called the `Bizarro Pipe`; the `Bizarro Pipe` is a first-rate pipe, faster than other pipes, and interferes less with debugging than other pipes).

Both languages have had this application capability for a very long time. We are using `Pandas` and `pipe()` as our example, but any package that whose methods return a reference to the object being worked on (or a reference to a replacement object) can be treated as a pipe-able object. If the class further implements one function re-director method (such as `pipe()`) then a lot more becomes practical. Here is another example showing how additional named and unnamed arguments can be handled.

``````def add_delta_to_column(df, colname, delta):
df[colname] = df[colname] + delta
return df``````
``````df .
groupby("group") .
agg({"value":["max", "min"], "cost":["mean"]}) .
pipe(print, "DEBUG1", sep = " | ")``````
``````      value     cost
max min mean
group
a         1   1    5
b         3   2   15 | DEBUG1``````

So depending on your point of view: “piping is poor-persons’s method chaining” or “method chaining is poor-persons’s piping” (taken from the usual quote comparing objects and closures).

If one wants to go further, there are a number of `Python` packages adding additional significant piping capabilities (either through notation, operator overloading, or other methods).

And that is piping versus method chaining.

Categories: Tutorials

Tagged as: ### jmount

Data Scientist and trainer at Win Vector LLC. One of the authors of Practical Data Science with R.
{"ft_lang_label":"__label__en","ft_lang_prob":0.8277351,"math_prob":0.88920426,"size":4067,"snap":"2023-14-2023-23","text_gpt3_token_len":1029,"char_repetition_ratio":0.1023874,"word_repetition_ratio":0.06495468,"special_character_ratio":0.26186377,"punctuation_ratio":0.12998714,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.9800416,"pos_list":[0,1,2],"im_url_duplicate_count":[null,null,null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2023-03-25T11:47:26Z\",\"WARC-Record-ID\":\"<urn:uuid:468d692b-563f-497b-a850-814546bb3309>\",\"Content-Length\":\"52958\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:e7ac5e39-189f-4e55-9789-9d95eb1e98fd>\",\"WARC-Concurrent-To\":\"<urn:uuid:97189627-9980-48f6-9625-c7a592dec1ca>\",\"WARC-IP-Address\":\"192.0.78.131\",\"WARC-Target-URI\":\"https://win-vector.com/2019/04/14/piping-is-method-chaining/\",\"WARC-Payload-Digest\":\"sha1:V77QBXKSZYTSA7YYHRCHWK2CSYBFGHHU\",\"WARC-Block-Digest\":\"sha1:P3NURYKHEY36WYVSTGU6RGNP2XEYJ6SX\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2023/CC-MAIN-2023-14/CC-MAIN-2023-14_segments_1679296945323.37_warc_CC-MAIN-20230325095252-20230325125252-00469.warc.gz\"}"}