是否有Python的等效PHP @
?
@function_which_is_doomed_to_fail();
我一直用这个块:
try:
foo()
except:
pass
但我知道必须有更好的方法。
有谁知道我如何将该代码进行Pythonic化?
我认为在该代码中添加一些上下文是合适的:
for line in blkid:
line = line.strip()
partition = Partition()
try:
partition.identifier = re.search(r'^(/dev/[a-zA-Z0-9]+)', line).group(0)
except:
pass
try:
partition.label = re.search(r'LABEL="((?:[^"\\]|\\.)*)"', line).group(1)
except:
pass
try:
partition.uuid = re.search(r'UUID="((?:[^"\\]|\\.)*)"', line).group(1)
except:
pass
try:
partition.type = re.search(r'TYPE="((?:[^"\\]|\\.)*)"', line).group(1)
except:
pass
partitions.add(partition)
答案 0 :(得分:5)
你正在寻找的是反pythonic,因为:
Python的禅宗,蒂姆·彼得斯 美丽胜于丑陋 明确胜过隐含。
简单比复杂更好 复杂比复杂更好 扁平比嵌套好。
稀疏比密集更好 可读性很重要 特殊情况不足以违反规则。
虽然实用性超过了纯度 错误绝不应该默默无闻 除非明确沉默。
面对模棱两可,拒绝猜测的诱惑 应该有一个 - 最好只有一个 - 明显的方式来做到这一点 虽然这种方式起初可能并不明显,除非你是荷兰人 现在总比没有好。
虽然现在永远不会比正确更好 如果实施很难解释,那是个坏主意 如果实施很容易解释,那可能是个好主意 命名空间是一个很棒的主意 - 让我们做更多的事情!
在你的情况下,我会使用这样的东西:
match = re.search(r'^(/dev/[a-zA-Z0-9]+)', line)
if match:
partition.identifier = match.group(0)
你有3行而不是4行。
答案 1 :(得分:2)
没有更好的方法。在任何语言中,默默地忽略错误都是不好的做法,所以它自然不是Pythonic。
答案 2 :(得分:1)
请不要让Python像PHP一样。您应始终明确捕获最具体的错误。捕捉并忽略所有这些错误并不是最佳实践。这是因为它可以隐藏其他问题并使bug更难找到。但是在RE的情况下,你应该检查它返回的None值。例如,您的代码:
label = re.search(r'LABEL="((?:[^"\\]|\.)*)"', line).group(1)
如果不匹配则引发AttributeError,因为如果没有匹配,re.search
将返回None。但如果有匹配但你的代码中有拼写错误怎么办:
label = re.search(r'LABEL="((?:[^"\\]|\.)*)"', line).roup(1)
即使存在匹配,也会引发AttributeError。但是使用catchall异常并忽略它会掩盖你的错误。在这种情况下,你永远不会匹配一个标签,在你以其他方式找到它之前你永远不会知道它,例如最终注意到你的代码永远不会与标签匹配(但希望你对这种情况进行单元测试......)
对于RE,通常的模式是:
matchobj = re.search(r'LABEL="((?:[^"\\]|\.)*)"', line)
if matchobj:
label = matchobj.group(1)
不需要尝试在此处捕获异常,因为没有异常。除了...当有类似错字引起的例外时。
答案 3 :(得分:1)
使用数据驱动设计而不是重复自己。命名相关组也可以更容易地避免组索引错误:
_components = dict(
identifier = re.compile(r'^(?P<value>/dev/[a-zA-Z0-9]+)'),
label = re.compile(r'LABEL="(?P<value>(?:[^"\\]|\\.)*)"'),
uuid = re.compile(r'UUID="(?P<value>(?:[^"\\]|\\.)*)"'),
type = re.compile(r'TYPE="(?P<value>(?:[^"\\]|\\.)*)"'),
)
for line in blkid:
line = line.strip()
partition = Partition()
for name, pattern in _components:
match = pattern.search(line)
value = match.group('value') if match else None
setattr(partition, name, value)
partitions.add(partition)
答案 4 :(得分:1)
基于Gabi Purcanu的回答以及您希望凝聚成一行的愿望,您可以将他的解决方案封装到一个函数中并减少您的示例:
def cond_match(regexp, line, grp):
match = re.search(regexp, line)
if match:
return match.group(grp)
else:
return None
for line in blkid:
line = line.strip()
partition = Partition()
partition.identifier = cond_match(r'^(/dev/[a-zA-Z0-9]+)', line, 0)
partition.label = cond_match(r'LABEL="((?:[^"\\]|\\.)*)"', line, 1)
partition.uuid = cond_match(r'UUID="((?:[^"\\]|\\.)*)"', line, 1)
partition.type = cond_match(r'TYPE="((?:[^"\\]|\\.)*)"', line, 1)
partitions.add(partition)
答案 5 :(得分:0)
Python中有警告控制 - http://docs.python.org/library/warnings.html
编辑后:
您可能想在尝试获取组之前检查它是否不是None
。
同时在组上使用len()来查看你有多少组。 “通过”错误绝对不是可行的方法。