[python] 파이썬에서 중첩 된 try / except 블록이 좋은 프로그래밍 습관입니까?

속성 호출로 사전에 액세스 해야하는 자체 컨테이너를 작성하고 있습니다. 컨테이너의 일반적인 사용법은 다음과 같습니다.

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"

난인지 확실하지 중첩 된 시도 / 블록은 다른 방법을 사용하는 것입니다, 그래서 좋은 연습입니다 제외 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 catch 블록을 사용하십시오.

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

가장 파이썬적이고 우아한 옵션은 무엇입니까?



답변

첫 번째 예는 완벽합니다. 공식 파이썬 문서조차도 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

추신. has_key()파이썬 2에서는 오랫동안 사용되지 않습니다 item in self.dict. 대신 사용하십시오 .


답변

Java에서는 실제로 흐름 제어에 예외를 사용하는 것은 좋지 않은 관행이지만 (주로 예외로 인해 jvm이 자원을 수집하도록 강요하기 때문에 ) 여기에는 더 중요한 두 가지 원칙이 있습니다 .Dy TypingEAFP . 이것은 기본적으로 객체가 작동한다고 생각하는 방식으로 객체를 사용하고 상황이 그렇지 않은 경우 처리하는 것이 좋습니다.

요약하면 유일한 문제는 코드가 너무 많이 들여 쓰기되는 것입니다. 느낌이 좋으면 lqc 제안과 같은 일부 중첩을 단순화하십시오.


답변

구체적인 예를 들어 실제로 중첩 할 필요는 없습니다. try블록 의 표현식이 성공하면 함수가 반환되므로 전체 시도 / 제외 블록 이후의 모든 코드는 첫 번째 시도가 실패한 경우에만 실행됩니다. 그래서 당신은 할 수 있습니다 :

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__일반 속성 조회 프로세스가 이미 실패했음을 알기 때문에 사용 하면 작업이 단순화됩니다.


답변

조심하십시오-이 경우 먼저 finally만지지 만 건너 뜁니다.

def a(z):
    try:
        100/z
    except ZeroDivisionError:
        try:
            print('x')
        finally:
            return 42
    finally:
        return 1


In [1]: a(0)
x
Out[1]: 1


답변

제 생각에는 이것이 파이썬을 다루는 가장 파이썬적인 방법 일 것입니다. 이는 내부 사전에 유지되는 “특수”속성 만 처리하면된다는 것을 의미하기 때문에 __getattr__()대신 정의합니다 __getattribute__().

def __getattr__(self, name):
    """only called when an attribute lookup in the usual places has failed"""
    try:
        return self.my_dict[name]
    except KeyError:
        raise AttributeError("some customized error message")


답변

파이썬에서는 허가보다 용서를 구하는 것이 더 쉽습니다. 중첩 된 예외 처리를 땀 흘리지 마십시오.

( has*어쨌든 거의 항상 표지 아래에서 예외를 사용합니다.)


답변

documentation 에 따르면 튜플이나 다음과 같은 여러 예외를 처리하는 것이 좋습니다.

import sys

try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except IOError as e:
    print "I/O error({0}): {1}".format(e.errno, e.strerror)
except ValueError:
    print "Could not convert data to an integer."
except:
    print "Unexpected error:", sys.exc_info()[0]
    raise