Search code examples
pythontoolz

python toolz - composing methods (in contrast to functions)


In the toolz project, is there anyway to treat an objects method similarly to a function, so i can better compose, curry, etc. ?
by better i mean readability, and similar performance

Heres a trivial example:

# given a list strings (names),
l = ["Harry"  ,
    "Sally  "    ,
    " bEn " ,
    " feDDy "  ]

# Lets pretend I want to apply a few simple string methods on each item in the
# list (This is just an example), and maybe replace as it's multi-airity.

# Traditional python list comprehension:
print([x.strip().lower().title().replace('H','T') for x in l ])

['Tarry', 'Sally', 'Ben', 'Feddy']

# my attempt, at toolz, same question with compose, curry,
# functools.partial.

from toolz.functoolz import pipe, thread_last
thread_last(l,
            (map , str.strip),
            (map , str.lower),
            (map , str.title),
            (map , lambda x: x.replace('H','T')), # any better way to do this?
            # I wish i had function/method `str.replace(__init_value__, 'H', 'T')` where the
            # `__init_value` is what I guess would go to the str constructor?
            list,
            print)

I don't like all extra lambda... and I couldn't imagine that would be ok for performance. Any tips on how to make this better with toolz?

With the operators module i can make most operators less painful and omit lambdas for things like addition, subtraction, etc.

Is there anything similar for method calls in recent versions of python?


Solution

  • Note that x.replace(y, z) is indeed str.replace(x, y, z). You can use a partial is a particular replacement is used often.

    Same applies to the rest of the methods: if you access a method via class, it's unbound, and the first argument (self) is a normal argument of a function. No magic around it. (Instance methods are partially applied, locking their self value to the instance.)

    So, I'd hazard thread_last(l, (map, pipe(str.strip, str.lower, str.title)) to apply three functions to each string element.

    (If you're into FP in Python, take a look at http://coconut-lang.org/)