beoliver
beoliver

Reputation: 5759

is it possible to treat string methods as functions?

is it possible to write a wrapper function for methods?

>>> lowtide = [ 'oh', 'i', 'do', 'like', 'to', 'be', 'beside', 'the', 'seaside' ]

>>> [ x.capitalize() for x in lowtide ]
['Oh', 'I', 'Do', 'Like', 'To', 'Be', 'Beside', 'The', 'Seaside']

>>> list(map(lambda x: x.capitalize(), lowtide))
['Oh', 'I', 'Do', 'Like', 'To', 'Be', 'Beside', 'The', 'Seaside']


>>> def mef(m):
...     def _mef(m,x):
...         return x.m()
...     return partial(_mef, m)
... 
>>> list(map(mef(capitalize), lowtide))

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'capitalize' is not defined

Upvotes: 2

Views: 998

Answers (3)

Jon Clements
Jon Clements

Reputation: 142206

Although you can use str.capitalize and unicode.capitalize, these can fail if you assume a certain type... The safest method is to just use:

from operator import methodcaller
capitalize = methodcaller('capitalize')

Which guarantees the correct method is used for the object, and also allows duck typing to be done successfully.

excerpt from a post from me to Google Groups/comp.lang.python 23 Aug 2010

Using methodcaller allows you to 'preserve' Python's duck-typing as well as any over-ridden methods in subclasses. In your example, this is probably overkill as you're only dealing with one class

Another (convoluted) example:

class mystr(str):
    def lower(self):
        return self.upper()

>>> s = mystr('abc')
>>> s.lower()
'ABC'

>>> lower = methodcaller('lower')
>>> lower(s)
'ABC'

>>> str.lower(s)
'abc'

^^^ Most likely incorrect

It also adds a further bit of flexibility (which can be emulated with functools.partial admittedly):

split_tab = methodcaller('split', '\t')
split_comma = methodcaller('split', ',')

Upvotes: 5

Andrew Clark
Andrew Clark

Reputation: 208545

Here is how you could rewrite your mef function to get this to work properly. The benefit here over using str.capitalize is that it will work for Unicode strings as well on Python 2.x:

def mef(m):
    def _mef(x):
        return getattr(x, m)()
    return _mef

list(map(mef('capitalize'), lowtide))

Note that this is essentially the same thing as using lambda x: x.capitalize().

Upvotes: 1

Sven Marnach
Sven Marnach

Reputation: 602155

You can simply do

list(map(str.capitalize, lowtide))

In Python 3.x, str.capitalize() is a function taking the single argument self.

In Python 2.x, str.capitalize() is an "unbound method", but behaves similar to a function taking a single argument.

Upvotes: 8

Related Questions