我必须从没有通用逻辑的文件名中解析一些数字。我想使用python的方式“尝试,你将被宽恕”,或尝试 - 除了结构。现在我要添加两个以上的案例。这样做的正确方法是什么?我现在想要嵌套尝试或尝试 - 除了传递,尝试 - 除 - 传递,...哪一个会更好还是别的什么?工厂方法也许(如何?)?
将来很容易扩展,因为会有更多的案例。
以下是我想要的(不起作用,因为每次尝试只能存在一个例程):
try:
# first try
imNo = int(imBN.split('S0001')[-1].replace('.tif',''))
except:
# second try
imNo = int(imBN.split('S0001')[-1].replace('.tiff',''))
except:
# final try
imNo = int(imBN.split('_0_')[-1].replace('.tif',''))
修改:
哇,谢谢你的回答,但没有模式匹配。我的坏,在开始时加上“一些共同的逻辑”(现在改为“没有共同的逻辑”,对此抱歉)。在上面的情况下,模式非常相似......让我添加一些完全不同的东西来说明问题。except:
if imBN.find('first') > 0: imNo = 1
if imBN.find('second') > 0: imNo = 2
if imBN.find('third') > 0: imNo = 3
...
答案 0 :(得分:10)
您可以提取公共结构并列出可能的参数:
tries = [
('S0001', '.tif'),
('S0001', '.tiff'),
('_0_', '.tif'),
]
for sep, subst in tries:
num = imBN.split(sep)[-1].replace(subst, '')
try:
imNo = int(num)
break
except ValueError:
pass
else:
raise ValueError, "String doesn't match any of the possible patterns"
这项技术可以通过使用lambdas轻松地适应任意表达式:
def custom_func(imBN):
if 'first' in imBN: return 1
if 'second' in imBN: return 2
tries = [
lambda: int(imBN.split('S0001')[-1].replace('.tif','')),
lambda: int(imBN.split('S0001')[-1].replace('.tiff','')),
lambda: int(imBN.split('_0_')[-1].replace('.tif','')),
lambda: custom_func(imBN),
]
for expr in tries:
try:
result = expr()
break
except:
pass
else:
# error
答案 1 :(得分:3)
在您的特定情况下,正则表达式将不再需要执行这些try-except块。这样的事情可能会抓住你的案例:
>>> import re
>>> re.match('.*(S0001|_0_)([0-9]+)\..*$', 'something_0_1234.tiff').groups()
('_0_', '1234')
>>> re.match('.*(S0001|_0_)([0-9]+)\..*$', 'somethingS00011234.tif').groups()
('S0001', '1234')
>>> re.match('.*(S0001|_0_)([0-9]+)\..*$', 'somethingS00011234.tiff').groups()
('S0001', '1234')
关于连续尝试 - 除外块的问题,Niklas B.的答案显然很棒。
修改强> 你正在做的是模式匹配,为什么不使用模式匹配库?如果正则表达式字符串困扰你,有更简洁的方法来做到这一点:
import re
matchers = []
sep = ['S0001', '_0_']
matchers.append(re.compile('^.*(' + '|'.join(sep) + ')(\d+)\..*$'))
matchers.append(some_other_regex_for_other_cases)
for matcher in matchers:
match = matcher.match(yourstring)
if match:
print match.groups()[-1]
与自定义函数兼容的另一种更通用的方法:
import re
matchers = []
simple_sep = ['S0001', '_0_']
simple_re = re.compile('^.*(' + '|'.join(sep) + ')(\d+)\..*$')
def simple_matcher(s):
m = simple_re.match(s)
if m:
return m.groups()[-1]
def other_matcher(s):
if s[3:].isdigit():
return s[3:]
matchers.append(simple_matcher)
matchers.append(other_matcher)
for matcher in matchers:
match = matcher('yourstring')
if match:
print int(match)