To answer your first question about why the list of empty values ββis not considered empty, it is because it contains something, even if these things are empty themselves. Think of it as a box with empty drawers.
The code below shows one way to modify the foo()
function to do what you want (and test). Your idea of ββwhat an empty list is was surprisingly difficult to develop, in part because it contradicts what the language itself considers empty. As you can see, all the logic involved in determining whether the list is βemptyβ according to your definition has been moved to a separate function called empty_list()
, since this probably has little to do with the rest of what foo()
has to achieve. It is not too difficult, and if nothing else gives you a good starting point.
Also, you did not say what it should do if the argument it passed is not a list of any type or was not a list, but does not contain only other lists or strings, therefore, as it is written, it will raise a TypeError
exception - something similar to how most Python built-in functions react when it happens to them. The following is an example code and its test result:
try: string_type = basestring except NameError: # probably Python 3.x string_type = str class _NULL(object): # unique marker object def __repr__(self): return '<nothing>' _NULL = _NULL() def empty_list(arg=_NULL): arg = arg if arg is not _NULL else [] if not isinstance(arg, (list, string_type)): raise TypeError elif isinstance(arg, string_type): return not len(arg) else: return len(arg) == 0 or all(empty_list(e) for e in arg) def foo(list_=None): if list_ is None or empty_list(list_): print 'list is empty' else: print 'list is not empty' testcases = [ _NULL, [], [''], ['', ''], ['', ['']], ['abc'], ['', 'abc'], [False], [None], [0], [0.0], [0L], [0j], [42], [{}], [{'':0}], [{'a':1}], False, None, 0, 0.0, 0L, 0j, 42, {}, {'':0}, {'a':1}, ] for arg in testcases: call = 'foo( {!r:s} ) ->'.format(arg) print '{!s:>20s}'.format(call), try: foo() if arg is _NULL else foo(arg) except TypeError: print 'illegal argument exception'
Here is the output that it produces using Python 2.7:
foo( <nothing> ) -> list is empty foo( [] ) -> list is empty foo( [''] ) -> list is empty foo( ['', ''] ) -> list is empty foo( ['', ['']] ) -> list is empty foo( ['abc'] ) -> list is not empty foo( ['', 'abc'] ) -> list is not empty foo( [False] ) -> illegal argument exception foo( [None] ) -> illegal argument exception foo( [0] ) -> illegal argument exception foo( [0.0] ) -> illegal argument exception foo( [0L] ) -> illegal argument exception foo( [0j] ) -> illegal argument exception foo( [42] ) -> illegal argument exception foo( [{}] ) -> illegal argument exception foo( [{'': 0}] ) -> illegal argument exception foo( [{'a': 1}] ) -> illegal argument exception foo( False ) -> illegal argument exception foo( None ) -> list is empty foo( 0 ) -> illegal argument exception foo( 0.0 ) -> illegal argument exception foo( 0L ) -> illegal argument exception foo( 0j ) -> illegal argument exception foo( 42 ) -> illegal argument exception foo( {} ) -> illegal argument exception foo( {'': 0} ) -> illegal argument exception foo( {'a': 1} ) -> illegal argument exception