[Python-3000] Making strings non-iterable
Nick Coghlan
ncoghlan at gmail.com
Thu Apr 20 11:25:53 CEST 2006
Barry Warsaw wrote:
> On Wed, 2006-04-19 at 20:17 +1000, Nick Coghlan wrote:
>
>> Unfortunately, the thread fizzled without generating any additional interest.
>> I don't recall the topic really coming up since then.
>
> Maybe because the proposal got too complex while trying to be so
> general?
One way to simplify it would be to special case strings rather than provide a
general stop list (this would be significantly simpler to do in C, too):
from itertools import chain
def walk(iterable, depth_first=True, iter_strings=False):
itr = iter(iterable)
while True:
for item in itr:
if isinstance(item, basestring):
# We have a string
# Don't iterate if flag is not set
# Never iterate if length is only 1
if not iter_strings or len(item) == 1:
yield item
continue
try:
subitr = iter(item)
except TypeError:
yield item
continue
if depth_first:
itr = chain(subitr, itr)
else:
itr = chain(itr, subitr)
break # Restart the inner for loop
else:
break # Finish the outer while loop
Py> seq = [['123', '456'], 'abc', 'abc', 'abc', 'abc', ['xyz']]
Py> seq
[['123', '456'], 'abc', 'abc', 'abc', 'abc', ['xyz']]
Py> list(walk(seq))
['123', '456', 'abc', 'abc', 'abc', 'abc', 'xyz']
Py> list(walk(seq, iter_strings=True))
['1', '2', '3', '4', '5', '6', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c',
'a', 'b', 'c', 'x', 'y', 'z']
Py> list(walk(seq, depth_first=False))
['abc', 'abc', 'abc', 'abc', '123', '456', 'xyz']
Py> list(walk(seq, depth_first=False, iter_strings=True))
['a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', '1', '2', '3',
'4', '5', '6', 'x', 'y', 'z']
--
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
---------------------------------------------------------------
http://www.boredomandlaziness.org
More information about the Python-3000
mailing list