[Python-Dev] Iterable String Redux (aka String ABC)

Steven D'Aprano steve at pearwood.info
Wed May 28 02:07:59 CEST 2008


(If you receive this twice, please excuse the duplicate email. 
User-error on my part, sorry.)

On Wed, 28 May 2008 08:23:38 am Raymond Hettinger wrote:

> A flatten() implementation doesn't really care about whether
> an input is a string which supports all the string-like methods
> such as capitalize().   Wouldn't it be better to write your
> version of flatten() with a registration function so that a user
> could specify which objects are atomic?  Otherwise, you
> will have to continually re-edit your flatten() code as you
> run across other non-stringlike objects that also need to
> be treated as atomic.

Just throwing a suggestion out there... 

def atomic(obj, _atomic=(basestring,)):
    try:
        return bool(obj.__atomic__)
    except AttributeError:
        if isinstance(obj, _atomic):
            return True
        else:
            try:
                iter(obj)
            except TypeError:
                return True
    return False

assert atomic("abc")
assert not atomic(['a', 'b', 'c'])

If built-in objects grew an __atomic__ attribute, you could simplify the 
atomic() function greatly:

def atomic(obj):
    return bool(obj.__atomic__)


However atomic() is defined, now flatten() is easy:

def flatten(obj):
    if atomic(obj):
        yield obj
    else:
        for item in obj:
            for i in flatten(item):
                yield i


If you needed more control, you could customise it using standard 
techniques e.g. shadow the atomic() function with your own version, 
sub-class the types you wish to treat differently, make __atomic__ a 
computed property instead of a simple attribute, etc.

Re-writing the above to match Python 3 is left as an exercise.


-- 
Steven


More information about the Python-Dev mailing list