[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

AltStyle によって変換されたページ (->オリジナル) /