空の値のリストが空と見なされない理由についての最初の質問に答えるには、それら自体が空であっても、リストに何かが含まれているためです。空の箱の箱のように考えてください。
以下のコードは、関数を変更しfoo()
て必要な処理を実行する(そしてテストする)1つの方法を示しています。空のリストが何であるかについてのあなたの概念は、言語自体が空であると見なすものに反するため、驚くほど考案するのが難しいものでした。ご覧のとおり、定義に従ってリストが「空」であるかどうかの判断を処理するすべてのロジックはempty_list()
、他の実行する必要があることとはほとんど関係がないため、呼び出される別の関数に移動されfoo()
ました。それは過度に複雑ではなく、他に何もなければ良い出発点を提供するべきではありません。
また、渡された引数がどのような種類のリストでもないか、リストであるが他のリストや文字列だけが含まれていない場合はどうすればよいかを言わなかったので、書かれているようにTypeError
例外が発生します-何かこれは、ほとんどの組み込みPython関数でこれが発生したときに応答する方法と似ています。以下は、サンプルコードとそのテスト出力です。
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'
Python2.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