[Python-3000] PEP 3100 Comments

Paul Moore p.f.moore at gmail.com
Sun May 7 13:35:43 CEST 2006


On 5/7/06, Talin <talin at acm.org> wrote:
> As an example, lets take a look at re.sub:
>
>    sub(pattern, repl, string[, count])
>
> The documentation says that "repl can be a string or a function" and
> "If repl is a function, it is called for every non-overlapping occurrence
> of pattern. The function takes a single match object argument, and
> returns the replacement string."
>
> This is certainly an example where different actions are taken based on the
> type of the object. And as for this being bad style - well, if the standard
> library can't be used as a model of API design -- especially a module that
> has been refactored as many times as re -- then what can be?
>
> Certainly this ability can be abused to create obscure code, but in this
> particular case the usage seems reasonable and relatively straight
> forward; I would hate to categorically forbid all uses of APIs that
> take actions based on object type rather than strict OOP.

Either way, the result of the following is undocumented (and arbitrary):

>>> import re
>>> re.sub('.', 'y', 'xxx')
'yyy'
>>> re.sub('.', lambda x: 'y', 'xxx')
'yyy'
>>> class guess(str):
...     def __call__(self, x): return 'z'
...
>>> re.sub('.', guess('y'), 'xxx')
'zzz'
>>> guess('y')
'y'
>>>

guess('y') is *both* a string and a callable. OK, so it's a contrived
example, but if there were two separate functions, re.sub and re.subfn
(or separate keyword parameter fn= and repl=, or any other explicit
API) the ambiguity would never occur.

It's not a big enough problem to break backward compatibility, but it
should probably be revisited for Py3K. And it's certainly not obvious
that the re.sub API is flawless...

Paul.


More information about the Python-3000 mailing list