【问题标题】:range over character in pythonpython中的字符范围
【发布时间】:2011-10-23 11:44:02
【问题描述】:

有没有办法跨越字符?像这样的。

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

希望大家帮忙

【问题讨论】:

  • 如果你只想要英文字母,有import stringstring.ascii_lowercase

标签: python range character


【解决方案1】:

这是自定义生成器的一大用途:

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)

然后:

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)

然后:

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

【讨论】:

  • 漂亮!对于要复制此内容的任何人,请记住 range(1,3) 迭代值 1 和 2(而不是三个),但 char_range('a','c') 将迭代 'a'、'b' 和'c'!
  • 您也可以添加可选步骤 arg:def char_range(c1, c2, step=1) ... ord(c1), ord(c2)+1, step
  • @wjandrea,对于负步骤不太适用,例如char_range('g','a',-1) 给出['g', 'f', 'e', 'd', 'c']
  • @alan 不错的收获!看起来这是ord(c2) 上的 +1 的错。所以将ord(c2)+1 替换为ord(c2) + (1 if step > 0 else -1)。尽管为了清楚起见,您可能希望将其排除在 range() 调用之外。
  • 这样做的问题在于,要生成 a-z,您需要知道 z 之后是哪个字符。不是特别舒服。最好避免使用名称«range»(使用 closedrange 或 inclusiverange 代替?)
【解决方案2】:
import string
for char in string.ascii_lowercase:
    print char

请参阅string constants 了解其他可能性,包括大写、数字、依赖于区域设置的字符,如果您想要多组中的所有字符,您可以像string.ascii_uppercase + string.ascii_lowercase 一样将所有这些连接在一起。

【讨论】:

    【解决方案3】:

    您必须将字符转换为数字,然后再转换回来。

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

    为了美观和可读性,您可以将其包装在生成器中:

    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))
    

    可以使用inclusive=False(默认)调用此生成器以模仿Python 的通常行为来排除结束元素,或者使用inclusive=True(默认)来包含它。所以使用默认的inclusive=False'a', 'z' 只会跨越从ay 的范围,不包括z

    如果ab中的任何一个是unicode,则以unicode返回结果,否则使用chr

    目前(可能)仅适用于 Py2。

    【讨论】:

    • 您可以将其隐藏在生成器中:请参阅我的答案。
    • 你的意思是你更喜欢ord's和chr's在你的脸上?如果你不得不多次这样做,你会在每个地方复制它吗?奇怪..
    • 所以我最好说“看起来更好”而不是“看起来更好”。
    【解决方案4】:

    这里还有其他很好的答案(我个人可能会使用 string.lowercase),但为了完整起见,您可以在小写 ascii 值上使用 map()chr()

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

    【讨论】:

      【解决方案5】:

      如果你有一个简短的固定字符列表,只需使用 Python 将字符串作为列表处理。

      for x in 'abcd':
          print x
      

      [x for x in 'abcd']
      

      【讨论】:

        【解决方案6】:

        我喜欢这样的方法:

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

        它当然可以更舒适地实现,但它快速、简单且可读性强。

        Python 3

        生成器版本:

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

        或者,如果你喜欢列表推导:

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

        第一个产量:

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

        而第二个产生:

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

        真的很方便:

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

        输出

        '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' '+' '/' 
        

        为什么是list()?没有base64chars 可能会成为生成器(取决于您选择的实现),因此只能在第一个循环中使用。

        Python 2

        可以使用 Python 2 存档类似的内容。但如果您也想支持 Unicode,它会复杂得多。为了鼓励您停止使用 Python 2 转而使用 Python 3,我不想在这里提供 Python 2 解决方案;)

        对于新项目,今天尽量避免使用 Python 2。还可以先尝试将旧项目移植到 Python 3,然后再扩展它们 - 从长远来看,这将是值得的!

        在 Python 2 中正确处理 Unicode 非常复杂,如果没有从一开始就内置支持,则几乎不可能将 Unicode 支持添加到 Python 2 项目中。

        提示如何将其反向移植到 Python 2:

        • 使用xrange 而不是range
        • 创建第二个函数 (unicodes?) 用于处理 Unicode:
          • 使用unichr 而不是chr 返回unicode 而不是str
          • 永远不要忘记将 unicode 字符串输入为 args 以使 ord 和数组下标正常工作

        【讨论】:

          【解决方案7】:
          for character in map(   chr, xrange( ord('a'), ord('c')+1 )   ):
             print character
          

          打印:

          a
          b
          c
          

          【讨论】:

            【解决方案8】:
            # 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)]
            

            【讨论】:

              【解决方案9】:

              受上面顶帖的启发,我想出了这个:

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

              【讨论】:

                【解决方案10】:

                对于大写字母:

                for i in range(ord('A'), ord('Z')+1):
                    print(chr(i))
                

                对于小写字母:

                for i in range(ord('a'), ord('z')+1):
                    print(chr(i))
                

                【讨论】:

                • 仅打印范围值时,将仅返回字符的 Unicode 值,在类型转换为 chr() 后,将返回正确的字符
                【解决方案11】:

                在这里使用@ned-batchelder 的答案,我正在为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)
                

                那么和内德的回答一样:

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

                谢谢内德!

                【讨论】:

                  【解决方案12】:

                  我也有同样的需求,我用了这个:

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

                  希望这会对某人有所帮助

                  【讨论】:

                  • 这是个好主意,对我的应用程序来说很优雅,例如:for c in string.ascii_uppercase(注意:OP 有一个范围结束“错误”)。
                  【解决方案13】:

                  使用 "for count in range" 和 chr&ord:

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

                  【讨论】:

                    【解决方案14】:

                    使用列表理解:

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

                    【讨论】:

                      【解决方案15】:

                      另一个选项(操作类似于范围 - 如果您希望停止包含,则添加 1 停止)

                      >>> 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']
                      

                      【讨论】:

                        【解决方案16】:

                        根据字符范围的复杂程度,使用正则表达式可能更方便:

                        import re
                        import string
                        
                        re.findall("[a-f]", string.printable)
                        # --> ['a', 'b', 'c', 'd', 'e', 'f']
                        
                        re.findall("[n-qN-Q]", string.printable)
                        # --> ['n', 'o', 'p', 'q', 'N', 'O', 'P', 'Q']
                        

                        这可以解决在 ASCII 表中意外包含数字、大写和小写字母之间的标点符号这一令人讨厌的问题。

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 2013-04-10
                          • 2016-08-11
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 2012-06-23
                          相关资源
                          最近更新 更多