range over character in python

喜夏-厌秋 提交于 2019-11-27 03:35:42
Ned Batchelder

This is a great use for a custom generator:

Python 2:

def char_range(c1, c2):
    """Generates the characters from `c1` to `c2`, inclusive."""
    for c in xrange(ord(c1), ord(c2)+1):
        yield chr(c)

then:

for c in char_range('a', 'z'):
    print c

Python 3:

def char_range(c1, c2):
    """Generates the characters from `c1` to `c2`, inclusive."""
    for c in range(ord(c1), ord(c2)+1):
        yield chr(c)

then:

for c in char_range('a', 'z'):
    print(c)
import string
for char in string.ascii_lowercase:
    print char

See string constants for the other possibilities, including uppercase, numbers, locale-dependent characters, all of which you can join together like string.ascii_uppercase + string.ascii_lowercase if you want all of the characters in multiple sets.

You have to convert the characters to numbers and back again.

for c in xrange(ord('a'), ord('z')+1):
    print chr(c) # resp. print unicode(c)

For the sake of beauty and readability, you can wrap this in a generator:

def character_range(a, b, inclusive=False):
    back = chr
    if isinstance(a,unicode) or isinstance(b,unicode):
        back = unicode
    for c in xrange(ord(a), ord(b) + int(bool(inclusive)))
        yield back(c)

for c in character_range('a', 'z', inclusive=True):
    print(chr(c))

This generator can be called with inclusive=False (default) to imitate Python's usual bhehaviour to exclude the end element, or with inclusive=True (default) to include it. So with the default inclusive=False, 'a', 'z' would just span the range from a to y, excluding z.

If any of a, b are unicode, it returns the result in unicode, otherwise it uses chr.

It currently (probably) only works in Py2.

There are other good answers here (personally I'd probably use string.lowercase), but for the sake of completeness, you could use map() and chr() on the lower case ascii values:

for c in map(chr, xrange(97, 123)):
   print c

If you have a short fixed list of characters, just use Python's treatment of strings as lists.

for x in 'abcd':
    print x

or

[x for x in 'abcd']
for character in map(   chr, xrange( ord('a'), ord('c')+1 )   ):
   print character

prints:

a
b
c
# generating 'a to z' small_chars.
small_chars = [chr(item) for item in range(ord('a'), ord('z')+1)]
# generating 'A to Z' upper chars.
upper_chars = [chr(item).upper() for item in range(ord('a'), ord('z')+1)]

I like an approach which looks like this:

base64chars = list(chars('AZ', 'az', '09', '++', '//'))

It certainly can be implemented with a lot of more comfort, but it is quick and easy and very readable.

Python 3

Generator version:

def chars(*args):
    for a in args:
        for i in range(ord(a[0]), ord(a[1])+1):
            yield chr(i)

Or, if you like list comprehensions:

def chars(*args):
    return [chr(i) for a in args for i in range(ord(a[0]), ord(a[1])+1)]

The first yields:

print(chars('ĀĈ'))
<generator object chars at 0x7efcb4e72308>
print(list(chars('ĀĈ')))
['Ā', 'ā', 'Ă', 'ă', 'Ą', 'ą', 'Ć', 'ć', 'Ĉ']

while the second yields:

print(chars('ĀĈ'))
['Ā', 'ā', 'Ă', 'ă', 'Ą', 'ą', 'Ć', 'ć', 'Ĉ']

It is really convenient:

base64chars = list(chars('AZ', 'az', '09', '++', '//'))
for a in base64chars:
   print(repr(a),end='')
print('')
for a in base64chars:
   print(repr(a),end=' ')

outputs

'A''B''C''D''E''F''G''H''I''J''K''L''M''N''O''P''Q''R''S''T''U''V''W''X''Y''Z''a''b''c''d''e''f''g''h''i''j''k''l''m''n''o''p''q''r''s''t''u''v''w''x''y''z''0''1''2''3''4''5''6''7''8''9''+''/'
'A' 'B' 'C' 'D' 'E' 'F' 'G' 'H' 'I' 'J' 'K' 'L' 'M' 'N' 'O' 'P' 'Q' 'R' 'S' 'T' 'U' 'V' 'W' 'X' 'Y' 'Z' 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 'u' 'v' 'w' 'x' 'y' 'z' '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' '+' '/' 

Why the list()? Without base64chars might become a generator (depending on the implementation you chose) and thus can only be used in the very first loop.

Python 2

Similar can be archived with Python 2. But it is far more complex if you want to support Unicode, too. To encourage you to stop using Python 2 in favor of Python 3 I do not bother to provide a Python 2 solution here ;)

Try to avoid Python 2 today for new projects. Also try to port old projects to Python 3 first before extending them - in the long run it will be worth the effort!

Proper handling of Unicode in Python 2 is extremely complex, and it is nearly impossible to add Unicode support to Python 2 projects if this support was not build in from the beginning.

Hints how to backport this to Python 2:

  • Use xrange instead of range
  • Create a 2nd function (unicodes?) for handling of Unicode:
    • Use unichr instead of chr to return unicode instead of str
    • Never forget to feed unicode strings as args to make ord and array subscript work properly
sjs7007

Inspired from the top post above, I came up with this :

map(chr,range(ord('a'),ord('z')+1))                     

Use "for count in range" and chr&ord:

print [chr(ord('a')+i) for i in range(ord('z')-ord('a'))]

Use list comprehension:

for c in [chr(x) for x in range(ord('a'), ord('z'))]:
    print c

Using @ned-batchelder's answer here, I'm amending it a bit for python3

def char_range(c1, c2):
    """Generates the characters from `c1` to `c2`, inclusive."""
    """Using range instead of xrange as xrange is deprecated in Python3""" 
    for c in range(ord(c1), ord(c2)+1):
        yield chr(c)

Then same thing as in Ned's answer:

for c in char_range('a', 'z'):
    print c

Thanks Ned!

Another option (operates like range - add 1 to stop if you want stop to be inclusive)

>>> import string
>>> def crange(arg, *args):
...     """character range, crange(stop) or crange(start, stop[, step])"""
...     if len(args):
...         start = string.ascii_letters.index(arg)
...         stop = string.ascii_letters.index(args[0])
...     else:
...         start = string.ascii_letters.index('a')
...         stop = string.ascii_letters.index(arg)
...     step = 1 if len(args) < 2 else args[1]
...     for index in range(start, stop, step):
...         yield string.ascii_letters[index]
...
>>> [_ for _ in crange('d')]
['a', 'b', 'c']
>>>
>>> [_ for _ in crange('d', 'g')]
['d', 'e', 'f']
>>>
>>> [_ for _ in crange('d', 'v', 3)]
['d', 'g', 'j', 'm', 'p', 's']
>>>
>>> [_ for _ in crange('A', 'G')]
['A', 'B', 'C', 'D', 'E', 'F']

i had the same need and i used this :

chars = string.ascii_lowercase
range = list(chars)[chars.find('a'):chars.find('k')+1]

Hope this will Help Someone

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!