Parse a string as a list of words and parse characters
The documentation for re.split says:


  If capturing parentheses are used in pattern, then the text of all groups in the pattern are also returned as part of the resulting list.


For example:

&gt;&gt;&gt; import re
&gt;&gt;&gt; re.split('( )', 'hello world')
['hello', ' ', 'world']


If the string starts or ends with a separator, you get an empty string:

&gt;&gt;&gt; re.split('( )', ' a b c ')
['', ' ', 'a', ' ', 'b', ' ', 'c', ' ', '']


You probably don't want these empty strings, so you should filter them out:

&gt;&gt;&gt; [w for w in re.split('( )', ' a b c ') if w]
[' ', 'a', ' ', 'b', ' ', 'c', ' ']


So your parse_chars function would become:

[w for w in re.split('([^0-9A-Za-z])', string) if w]


For example:

&gt;&gt;&gt; [w for w in re.split('([^0-9A-Za-z])', '10 green bottles!') if w]
['10', ' ', 'green', ' ', 'bottles', '!']