The default sort order for ASCII strings from Python's sorted function is lexicographic (or 'ASCIIbetical'):
>>> li=['1', '20', '100', '11']
>>> sorted(li)
['1', '100', '11', '20']
Compared to integer magnitude when those list values are integers:
>>> sorted(map(int, li))
[1, 11, 20, 100]
ie, the magnitude of the numbers in strings to the human eye is different than the same strings to the computer's eye. (Written about more extensively in Codinghorror)
To fix it, we need to separate the letters from the numbers and convert the numbers to integers (or floats).
The easiest way is with a regex that captures all numbers, converts to ints then all letters.
This sorts into your target:
li1='''\
01AA01
01AS01
01NA01
01BA01
01MA01
01AA02
01AS02
02BA01'''.splitlines()
tgt='''\
01AA01
01AS01
01BA01
01MA01
01NA01
01AA02
01AS02
02BA01'''.splitlines()
import re
def kf(s):
nums=map(int, re.findall(r'(\d+)', s))
lets=re.findall(r'([a-zA-Z]+)', s)
return nums+lets
print tgt==sorted(li1, key=kf)
# True
Or, one line:
>>> tgt==sorted(li1, key=lambda s: map(int, re.findall(r'(\d+)', s))+re.findall(r'(\D+)', s))
True
Edit based on comments
The text of the question states:
I want it to be ordered numerically in the first section 01,02,03...
and then alphabetically for AA, AS, BA in the second portion, and
numerically again for the third section.
However, the example shows that this is not the case.
We can sort based on the pattern of (int, letters, int) with split:
>>> [re.split(r'(\D+)', e) for e in li1]
[['01', 'AA', '01'], ['01', 'AS', '01'], ['01', 'NA', '01'], ['01', 'BA', '01'], ['01', 'MA', '01'], ['01', 'AA', '02'], ['01', 'AS', '02'], ['02', 'BA', '01']]
>>> sorted(li1, key=lambda s: [int(e) if e.isdigit() else e for e in re.split(r'(\D+)', s)])
['01AA01', '01AA02', '01AS01', '01AS02', '01BA01', '01MA01', '01NA01', '02BA01']
# ^^ ^^ etc '01AA02', before '01AS01' in the example
By inspection, the pattern of the POSTED example is (int, int, letters) which can be seen here:
>>> [map(int, re.findall(r'(\d+)', s))+re.findall(r'(\D+)', s) for s in li1]
[[1, 1, 'AA'], [1, 1, 'AS'], [1, 1, 'NA'], [1, 1, 'BA'], [1, 1, 'MA'], [1, 2, 'AA'], [1, 2, 'AS'], [2, 1, 'BA']]
If the TEXT is correct, use the split form of sort I have; if the EXAMPLE is correct, use the nums+lets form.