python中嵌套的try/except块是一个好的编程实践吗?

2024-04-26 07:26:05 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在编写自己的容器,它需要通过属性调用来访问内部的字典。容器的典型用途如下:

dict_container = DictContainer()
dict_container['foo'] = bar
...
print dict_container.foo

我知道写这样的东西可能很愚蠢,但这是我需要提供的功能。我在考虑用以下方式实现这一点:

def __getattribute__(self, item):
    try:
        return object.__getattribute__(item)
    except AttributeError:
        try:
            return self.dict[item]
        except KeyError:
            print "The object doesn't have such attribute"

我不确定嵌套的try/except块是否是一个好的实践,因此另一种方法是使用hasattr()has_key()

def __getattribute__(self, item):
        if hasattr(self, item):
            return object.__getattribute__(item)
        else:
            if self.dict.has_key(item):
                return self.dict[item]
            else:
                raise AttributeError("some customised error")

或者使用其中一个,然后尝试这样的catch block:

def __getattribute__(self, item):
    if hasattr(self, item):
        return object.__getattribute__(item)
    else:
        try:
            return self.dict[item]
        except KeyError:
            raise AttributeError("some customised error")

哪一种选择是最性感和优雅的?


Tags: selfreturnifobjectcontainerdefitemelse
3条回答

你的第一个例子很好。甚至官方的Python文档也推荐这种称为EAFP的样式。

就我个人而言,我更喜欢在不需要嵌套的情况下避免嵌套:

def __getattribute__(self, item):
    try:
        return object.__getattribute__(item)
    except AttributeError:
        pass  # fallback to dict
    try:
        return self.dict[item]
    except KeyError:
        raise AttributeError("The object doesn't have such attribute") from None

PS.has_key()在Python 2中已经被弃用了很长一段时间。改用item in self.dict

在Java中,使用异常进行流控制确实是一种不好的做法(主要是因为异常迫使jvm收集资源(more here)),而在Python中,有两个重要的原则:Duck TypingEAFP。这基本上意味着你被鼓励试着用你认为它会起作用的方式来使用一个对象,并在事情不是这样的时候处理它。

总之,唯一的问题是代码缩进太多。如果你喜欢,试着简化一些嵌套,就像lqc建议的那样

对于您的特定示例,实际上不需要嵌套它们。如果try块中的表达式成功,函数将返回,因此整个try/except块之后的任何代码都将仅在第一次尝试失败时运行。所以你可以做:

def __getattribute__(self, item):
    try:
        return object.__getattribute__(item)
    except AttributeError:
        pass
    # execution only reaches here when try block raised AttributeError
    try:
        return self.dict[item]
    except KeyError:
        print "The object doesn't have such attribute"

嵌套它们并不坏,但我觉得让它保持平放会使结构更加清晰:您依次尝试一系列的事情,并返回第一个有效的东西。

顺便说一下,您可能想考虑是否真的要在这里使用__getattribute__,而不是__getattr__。使用__getattr__将简化工作,因为您将知道正常的属性查找过程已经失败。

相关问题 更多 >