4

I'm coming into python from a javascript background. In JS we can do array-method chaining, and it's awesome (especially with arrow functions):

someArray
.filter(x => x.count > 10)
.sort((a, b) => a.count - b.count)
.map(x => x.name)

Is something like array-method chaining possible in python and, if not, then why on earth not?

0

4 Answers 4

7

In Python, you'd do:

from operator import attrgetter
map(lambda x: x.name, 
    sorted(filter(lambda x: x.count > 10, someArray), 
           key=attrgetter("count"))

Syntax is slightly different, but it should basically do the same. Does this answer your question?

Edit

If you really want a more "chain-like" syntax, you can take a look at toolz. From their docs:

>>> from toolz.curried import pipe, map, filter, get
>>> pipe(accounts, filter(lambda acc: acc[2] > 150),
...                map(get([1, 2])),
...                list)

Edit 2

Thanks to @mpium for suggesting PyFunctional, which seems to have an even cooler syntax for this:

from functional import seq

seq(1, 2, 3, 4)\
    .map(lambda x: x * 2)\
    .filter(lambda x: x > 4)\
    .reduce(lambda x, y: x + y)
# 14
Sign up to request clarification or add additional context in comments.

4 Comments

isn't there a key missing for the sorted function?
@hiroprotagonist you're right, should be fixed now. Thanks!
You may also want to look at PyFunctional which is similar to toolz
Great suggestion, I didn't know PyFunctional. I edited my answer, thanks ;-)
1

You can do method chaining but the builtin list type does not support the operations you are requesting as methods (e.g. map is a builtin). @Felix's excellent answer looks right to me in terms of doing the operations you gave in your example. If you want to chain methods, all that's required is that each method returns an object which implements the next method.

Simple example:

list("234").copy( # Copy once
  ).copy( # Twice
    ).append("Dog" # Returns None, so we can't continue chaining
      ).copy( # AttributeError because None has no method "copy"
        )

Comments

1

in python you could do something like a data pipeline like this (which is quite the opposite of method chaining...):

a1 = (item for item in someArray if item.count > 10)
a2 = sorted(a1, key=lambda x: x.count)
a3 = [item.name for item in a2]

note that a1 is a generator expression (and not a list); it does not store the elements but generate them on the fly.

you could of course string that together (which is much less readable for my taste):

[item.name for item in sorted(
 (item for item in someArray if item.count > 10), key=lambda x: x.count)]

note that in python it is customary for methods that change the instance (e.g. list.sort()) to return None. so simple method chaining does not work for a list.

if you work with a library that returns self for those functions, method chaining will work.

Comments

0

Yes, it does work.

Method chaining works in several languages. Usually you would return this or self or whatever the current object is from the method.

class Foo(object):
    def bar(self):
        print "Foo.bar called"
        return self
    def baz(self):
        print "Foo.baz called"
        return self

foo = Foo()
foo2 = foo.bar().baz()

A lot of inbuilt python list methods modify list inplace, so it is difficult to chain on top of them. But you can create wrapper classes around them if you want functionality

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.