[Numpy-discussion] Why are empty arrays False?

Michael Lamparski diagonaldevice at gmail.com
Tue Aug 22 14:04:25 EDT 2017

On Tue, Aug 22, 2017 at 12:31 PM, Chris Barker <chris.barker at noaa.gov>
> Personally, I've thought for years that Python's "Truthiness" concept is
a wart.
> Sure, empty sequences, and zero values are often "False" in nature,
> but truthiness really is application-dependent -- in particular, sometimes
> a value of zero is meaningful, and sometimes not.

I think truthiness is easily a wart in any dynamically-typed language (and
yet ironically, every language I can think of that has truthiness is
dynamically typed except for C++).  And yet for some reason it seems to be
pressed forward as idiomatic in python, and for that reason alone, I use
it.  These are questions I ask myself on a daily basis, just to support
this strange idiom:

- How close to the public API is this argument?
- Is '' a reasonable value for this string?
- How about an empty tuple?  Empty set?
- Should this sentinel value be None or a new object()?
- Is this list local to this function?
- Is the type of this optional argument always True?
- How liable are these answers to change with future refactoring?

which seems like a pretty big laundry list to keep in check for what's
supposed to be syntactic sugar.  In the end, I will admit that I think my
code "looks nice," but I think that's only because I've gotten used to
seeing it!

After answering all of these questions I tend to find that truthiness is
seldom usable in any sort of generic code.  These are the kinds of places
where I usually find myself using truthiness instead, and all involve
working with objects of known type:

# 1. A list used as a stack
while stack:
    top = stack.pop()

def read_config(d):
    # 2. Empty default value for a mutable argument that I don't mutate
    d = dict(d or {})

    a = d.pop('a')
    b = d.pop('b')

    # 3. Validating configuration
    if d:
        warn('unrecognized config keys: {!r}'.format(list(d)))

# 4. Oddball cases, e.g. the "linked list" (a, (b, (c, (d, (e, None)))))
def iter_linked_list(node):
    while node:
        value, node = node
        yield value

# 5. ...more oddball stuff...
def format_call(f, *args, **kw):
    arg_s = ', '.join(repr(x) for x in args)
    kw_s = ', '.join(f'{k:!s}={v:!r}' for k,v in kw.items())
    sep = ', ' if args and kw else ''
    return f'{f.__name__}({arg_s}{sep}{kw_s})'

Meanwhile, for an arbitrary iterator taken as an argument, if you want it
to have at least one element for some reason, then good luck; truthiness
will not help you.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/numpy-discussion/attachments/20170822/2ea70421/attachment.html>

More information about the NumPy-Discussion mailing list