[Tutor] calling a method directly

Peter Otten __peter__ at web.de
Tue Apr 21 10:24:09 CEST 2015


Jim Mooney wrote:

> Is there any difference between these two since they give the same result,
> and when is the second preferred?
> 
>>>> x = 'ABE'
>>>> x.lower()
> 'abe'
>>>> str.lower(x)
> 'abe'

You may call str.lower() explicitly for subclasses of str. If the subclass
overrides the lower() method there is a difference:
 
>>> class MyStr(str):
...     def lower(self): return "lower({!r})".format(self)
... 
>>> x = MyStr("ABC")
>>> x.lower()
"lower('ABC')"
>>> str.lower(x)
'abc'

I don't think the second form is ever preferred, but if you know in advance
that you are dealing only with strings a lazy person may sometimes write

str.lower

instead of the more conventional

def lower(s):
    return s.lower()

>>> words = "abrufen anrufen Anrufer".split()
>>> sorted(words)
['Anrufer', 'abrufen', 'anrufen']
>>> sorted(words, key=str.lower)
['abrufen', 'anrufen', 'Anrufer']
>>> sorted(words, key=lambda s: s.lower())
['abrufen', 'anrufen', 'Anrufer']

The main disadvantage of invoking an unbound method is that it defeats
"duck-typing" (the code works with every object that has a lower() method
returning a string), and that is more common and more useful than you might
think after reading the following example:

>>> class Cow:
...     def lower(self): return "moo"
...     def __repr__(self): return "<Lisa the cow>"
... 
>>> words.append(Cow())

Lisa provides the interface needed for the sort operation

>>> sorted(words, key=lambda s: s.lower())
['abrufen', 'anrufen', 'Anrufer', <Lisa the cow>]

but is not exactly a str:

>>> sorted(words, key=str.lower)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: descriptor 'lower' requires a 'str' object but received a 'Cow'

Moo ;)




More information about the Tutor mailing list