2012-06-07 3 views
1

나는 문을 제외하고 시도의 긴 목록을 가지고 :파이썬에서 Try-Except 구문의 긴 목록을 간략하게 대체 하시겠습니까?

try: 
     uri = entry_obj['media$group']['media$content'][0]['url'] 
    except (KeyError, IndexError): 
     uri = None 
    try: 
     position = entry_obj['yt$position']['$t'] 
    except KeyError: 
     position = None 
    try: 
     description = entry_obj['content']['$t'] 
    except KeyError: 
     description = None 
    try: 
     seconds = entry_obj['media$group']['yt$duration']['seconds'] 
    except KeyError: 
     seconds = None 
    try: 
     thumbnails = entry_obj['media$group']['media$thumbnail'] 
    except KeyError: 
     thumbnails = None 

이 작성하는 더 간결한 방법이 있나요?

답변

9

당신은 get() 전화에 기본 값을 사용하는 것이 무엇인지 파악의 타이어 단지 도우미 함수를 작성하는 경우 조금이라도 호출하면 헬퍼 함수를 ​​강화하여 키에 대한 단일 문자열을 가져오고 공백으로 분할 할 수 있습니다. 당신이하지 않는 방법은 너무 많은 따옴표를 입력하고, 우리는 또한 기본값 인수를 추가 할 수 있습니다 : 나는 kindall의 방법을 비교하는 방법 확실하지,이 작업을 수행하는 또 다른 좋은 방법을 생각

def resolve(root, keys, default=None): 
    for key in keys.split(): 
     try: 
      root = root[key] 
     except (TypeError, KeyError): 
      try: 
       root = root[int(key)] 
      except (IndexError, ValueError, KeyError): 
       return default 

uri = resolve(entry_obj, 'media$group media$content 0 url', '') 
+0

+1 비슷한 일을 반복적으로 수행 할 때 뭔가를 일반적으로 수행하는 함수를 작성합니다. 나는 종종 프로그래머가 이것을하지 않는 빈도에 놀란다. 두 번째 버전은 나에게보기 흉하게 보인다. 이제 키는 공백을 포함 할 수 없으며 목록의 dicts 또는 int에있는 문자열 이외의 다른 문자가 될 수 없습니다. 첫 번째 것은 중첩 된 컨테이너에서 키의 체인을 찾는 것을 지원합니다. 여기서 필요한 것은'__getitem__'을 지원하고 키가 발견되지 않으면 KeyError 또는 IndexError를 던집니다. 항상 긴 긴 문자열을 입력하고 .split() 직접 입력 할 수 있습니다. – Ben

+0

그래, 두 번째는 문자열과 int 만 지원하며 문자열에는 공백이 포함될 수 없다는 제한이 있습니다. – kindall

+0

kindall, 방금 try-excepts를 대체하기 위해 방금 게시 한 방법에 대해 어떻게 생각합니까? 나는 파이썬에 익숙하지 않으므로 람다의 나쁜 사용인지 확신 할 수 없다. – Michael

1

사용하는 대신 사전의 get 방법 :

position = entry_object.get('yt$position').get('$t') 

get 당신을 위해 존재하지 않는 키의 경우를 처리하고, 그 경우에 대신 당신에게 (변하기 쉬워) 대체 값을 제공 할 것입니다. 처음에는 IndexError을 먼저 처리해야하지만, 바로 except KeyError: 인 모든 항목이 사라집니다. 그런 다음

def resolve(root, *keys): 
    for key in keys: 
     try: 
      root = root[key] 
     except (KeyError, IndexError): 
      return None 
    return root 

그냥 쓰기, 예를 들면 :

uri = resolve(entry_obj, 'media$group', 'media$content', 0, 'url') 

이를 단순화하기 위해

+2

당신은 통과해야하는 것 :

def res(self, property): try: return property() except (KeyError, IndexError): return None 

그런 다음에 문을 제외하고 시도 - 더 교체 : 우리는 첫 번째 방법의 속성을 정의 두 번째 것은 정상적으로 첫 번째 것이면 정상적으로 종료됩니다. 두 번 조회해도 괜찮지 만'seconds = entry_obj.get ('media $ group', {}). get ('yt $ duration', {}). get ('seconds')'꽤 끔찍합니다. 그리고이 평야는 예제의 첫 번째 줄과 같은 경우에는 작동하지 않습니다. 예를 들어, 모든 dict 조회가 아닙니다 (나머지는 있습니다.). 보통 .get은 일반적으로 매우 안전합니다. "dict-like"객체). – Ben

+2

다음에 추가하려면 :주의 깊게 계획하면 기본값을 사용하여 나머지 식을 계속 평가할 수 있습니다. 예를 들어 OP의 코드 스 니펫의 첫 번째 할당은 다음과 같이 쓸 수 있습니다. 'uri = entry_obj.get ('media $ group ', {}). get ('media $ content ', [{}]) [0] .get ('url')'. 'media {content} '에 대한'get'에있는'[{}}'는 빈 사전이있는 단일 요소 목록을 반환하므로 다음 두 작업이 항상 성공할 수 있습니다. – kindall

2

. 순서에서 첫 번째`get`에 기본으로`} {`

url = res(lambda: entry_obj['media$group']['media$content'][0]['url']) 
    position = res(lambda: entry_obj['yt$position']['$t']) 
    description = res(lambda: entry_obj['content']['$t']) 
    duration = res(lambda: entry_obj['media$group']['yt$duration']['seconds']) 
    thumbnails = res(lambda: entry_obj['media$group']['media$thumbnail']) 
+0

재미 있고 좋은 대안이다. 호출자가 선택적으로 catch 될 예외와 원하는 기본값을 전달할 수 있도록함으로써보다 일반적인 것을 만들 수도 있습니다. – kindall

관련 문제