【问题标题】:re.search() TypeError: cannot concatenate 'str' and 'NoneType' objectsre.search() TypeError: 不能连接 'str' 和 'NoneType' 对象
【发布时间】:2015-06-27 19:25:08
【问题描述】:

如果我执行re.search("(\d+)x",下面的代码将按预期工作。

但是,如果我添加替代搜索 re.search("(\d+)x|x(\d+)" 我会得到:

TypeError: cannot concatenate 'str' and 'NoneType' objects

代码:

fundleverage = None
regex_fundleverage = None
regex_fundleverage = re.search(r"(\d+)x|x(\d+)", instrument_name, flags=re.IGNORECASE)
if funddirection == "Long" and not regex_fundleverage == None:
    fundleverage = "+" + regex_fundleverage.group(1) + "00"
if funddirection == "Short" and not regex_fundleverage == None:
    fundleverage = "-" + regex_fundleverage.group(1) + "00"
print "Fundleverage: %s" % fundleverage

错误当然是因为我尝试将 str "+""00"None 连接起来。

我的问题是为什么在 re.search() 中只有一个查找时选择 group(1) 有效,但如果有两个替代查找则不起作用。

它正在搜索的字符串不包含"(\d+)x""x(\d+)" 这两个选项,只有一个是可能的。

示例字符串:

"Boost LevDAX 3x Daily ETP"
"ComStage LevDAX x2 UCITS ETF"

【问题讨论】:

  • 如果您想要两个输出,请不要在re.search 中使用上述正则表达式,因为一旦找到第一个匹配项,搜索就会停止。
  • @AvinashRaj 字符串中只有一个备选方案。我是否正确理解它只会“寻找”第一个替代方案而不是第二个替代方案,因此如果不存在则将其设为“无”?
  • 从不与无比较
  • 如果我搜索 re.findall 我得到:AttributeError: 'list' object has no attribute 'group'
  • re.findall 将返回找到的项目列表而不是组

标签: python regex


【解决方案1】:

我会这样做:

regex_fundleverage = re.findall('(?<=x)\d+|\d+(?=x)',instrument_name, flags=re.IGNORECASE) 

if funddirection == "Long" and regex_fundleverage:
    fundleverage = "+" + regex_fundleverage[0] + "00"

if funddirection == "Short" and regex_fundleverage:
    fundleverage = "-" + regex_fundleverage[0] + "00"

print "Fundleverage: %s" % fundleverage

【讨论】:

  • 返回None,我不确定正则表达式是否找到任何东西。将尝试找出错误。
  • 它丢失了and not regex_fundleverage = None:,你能更新你的答案吗?它现在可以工作了:)
  • @Winterflags...感谢您指出这一点,实际上,您可以这样做and regex_fundleverage :(不需要and not regex_fundleverage == None:).. 这意味着:and if there is anything in regex_fundleverage 如果regex_fundleverage 是清空它将是False .. :)
  • 哦,我明白了。谢谢 :) 我在您的代码前面保留了 fundleverage = Noneregex_fundleverage = None,现在它可以工作了。我会采用这个解决方案,因为它确实最接近最初的实现,但非常感谢所有帮助我的人!
【解决方案2】:

如果您只传递第一个字符串,您的程序就可以正常工作。但是当你传递第二个字符串时,第二组匹配。 group(1) 为 None,而 group(2) 为 2。

我会重写您的代码以分隔两个子表达式并使用if 语句来决定哪个匹配。

【讨论】:

    【解决方案3】:

    使用正则表达式检查字符串是否是您想要的形式,如果是,则只需使用\d+ 提取您想要的数字,因为您的字符串只能包含一个数字,如下所示:

    请注意,这样做的好处是,如果 leverage 不是您的字符串中的 x3x 等所需格式,则会引发错误

    import re
    fundleverage = None
    regex_fundleverage = None
    funddirection = "Long"
    instrument_name = "ComStage LevDAX 3x UCITS ETF"
    regex_fundleverage = re.search(r"(\b\d+x|x\d+\b)", instrument_name, flags=re.IGNORECASE)
    if  regex_fundleverage:
        regex_fundleverage = re.search(r"(\d+)", regex_fundleverage.group(0), flags=re.IGNORECASE)
    print(regex_fundleverage.group(0))
    if funddirection == "Long" and not regex_fundleverage == None:
        fundleverage = "+" + regex_fundleverage.group(1) + "00"
    if funddirection == "Short" and not regex_fundleverage == None:
        fundleverage = "-" + regex_fundleverage.group(1) + "00"
    print "Fundleverage: %s" % fundleverage
    

    【讨论】:

    • @Winterflags,不错:)
    • @Winterflags 如果您满意,也考虑接受答案 :)
    【解决方案4】:

    我确实使用了re.findall

    x = re.findall(r'(?<=x)\d+|\d+(?=x)', s)
    

    然后通过指定第一个索引来获取第一个元素,例如 x[0] 。你不会得到None 值。

    您也可以使用re.search 函数而不捕获组。

    re.search(r'(?<=x)\d+|\d+(?=x)', s).group()
    

    我想你想要 tjis,

    >>> import re
    >>> s = "Boost LevDAX 3x Daily ETP"
    >>> re.sub(r'\d+(?=x)|(?<=x)\d+', r'+\g<0>00', s)
    'Boost LevDAX +300x Daily ETP'
    

    >>> s = "Boost LevDAX 3x Daily ETP"
    >>> re.sub(r'(\d+)x|x(\d+)', lambda m: '+'+m.group(1)+'00' if m.group(1) else '+' + m.group(2) + '00', s)
    'Boost LevDAX +300 Daily ETP'
    >>> s = "ComStage LevDAX x2 UCITS ETF"
    >>> re.sub(r'(\d+)x|x(\d+)', lambda m: '+'+m.group(1)+'00' if m.group(1) else '+' + m.group(2) + '00', s)
    'ComStage LevDAX +200 UCITS ETF'
    

    根据您的评论,您的输入字符串中只有一个noxxno。如果是,那你可以试试这个,

    >>> s = "ComStage LevDAX x2 UCITS ETF"
    >>> fundleverage = re.sub(r'.*(?:(\d+)x|x(\d+)).*', lambda m: '+'+m.group(1)+'00' if m.group(1) else '+' + m.group(2) + '00', s)
    >>> print fundleverage
    

    【讨论】:

    • 嗯。 re.sub 解决方案正确替换为+300,但保留整个字符串"Boost LevDAX +300 Daily ETP"。它应该只将"+300" 传递给变量fundleverage。除此之外,它似乎还不错。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多