2014-10-30 1 views
1

x이 사전 일 경우 x.get(selector)과 같은 역할을하고 x이 클래스 인스턴스 인 경우 getattr(x, selector)과 같은 역할을하는 함수 f(x,selector)을 찾고 있습니다. 쓰기가 쉽지만, 내장되어 있습니까?사전이나 객체에서 아무렇게나 선택할 수있는 Python 내장이 있습니까?

+1

을 확인하는 것입니다. 'f (d,'keys ')'가 반환해야하는 것은 무엇입니까? 'd.keys' 또는'd [ 'keys']'? – georg

+1

파이썬에서는 애트리뷰트와 키의 차이를 신경 쓰지 않기 때문에 이것은 기본 제공되지 않습니다. 원하는 데이터를 모르는 경우 어떤 데이터를 처리합니까? –

답변

3

아니요, 기본 제공되지 않습니다.

그냥 할 수 단지 예외 처리 :

def f(x, selector): 
    try: 
     # Assume dictionary and has .get() method 
     return x.get(selector) 
    except AttributeError: 
     # Assumption incorrect, no .get() method present 
     return getattr(x, selector) 

또는 원하는 경우 두 줄을 바꿀 먼저 검사 할 속성.

_sentinel = object() 

def f(x, selector, default=_sentinel): 
    try: 
     # Assume mapping access is supported 
     result = x[selector] 
    except KeyError: 
     # key missing, fall through to default handling 
     pass 
    except TypeError: 
     # Assumption incorrect, not a mapping, fall back to attributes 
     result = getattr(x, selector, default) 
    if result is _sentinel: 
     raise KeyError(selector) 
    return default 

하지만 당신은 또한 두 번째 TypeError 처리기로 처리 KeyError 축소 첫째 getattr() 다시 떨어질 수 : 기본 지원

또 다른 변형,.

그러나 여기서 두 개의 네임 스페이스를 혼합하려고합니다. 키와 속성은 충돌 할 수 있으며, 속성 리터럴은 키보다 제한적입니다. 대부분의 파이썬 코드는 인이 두 가지를 섞어 쓰려고하지 않습니다. 왜이 작업을위한 내장 기능이 없습니다.

+0

행을 바꿔 예외를 KeyError로 변경하십시오. –

+0

@PauloScardine : 아니요, dict.get()은 KeyError를 발생시키지 않습니다. 그리고 만약 .get() 메소드가 없다면, 그것은 AttributeError를 발생시킬 것입니다. –

+0

객체가 a.get() 대신에'x.get '대신에'return x [selector]'를 사용할 것입니다. dict하지만 우연히 get 속성을 가지며,리스트와 유사한 객체를 처리하기 위해'IndexError'를 체크합니다. –

2

또 다른 방법은 dicts이 너무 객체 객체

의 유형
def f(x, selector): 
    if isinstance(x, dict): 
     return x.get(selector) 
    return getattr(x, selector) 
+0

하지만 Martijn의 답변이 더 우아하다고 생각합니다. –

0
In [297]: class Foo: 
    .....:  def __init__(self): 
    .....:   self.bar=5 
    .....:   


In [298]: def f(x, selector): 
    .....:  if hasattr(x, 'get'): 
    .....:   g = operator.itemgetter(selector) 
    .....:  else: # x is an object 
    .....:   g = operator.attrgetter(selector) 
    .....:  return g(x) 
    .....: 

In [299]: x = Foo() 

In [300]: f(x, 'bar') 
Out[300]: 5 

In [301]: d = {char:i for i,char in enumerate('asdf')} 

In [302]: f(d, 'a') 
Out[302]: 0 

In [303]: d 
Out[303]: {'a': 0, 's': 1, 'd': 2, 'f': 3} 
+0

'operator.itemgetter()'/'operator.attrgetter()'를 사용하면 왜 즉시 호출합니까? 간접 접근법을 사용하지 않고'getattr()'* 직접적으로 * 속성 접근을 시도 했습니까? –

+0

@MartijnPieters : 방금 생각한 것입니다. 나중에 사용할 수있는 함수를 구축하는 것이 맘에 들지만,이 시나리오에서는 너무 잔인 할 수 있습니다. 함수 내에서 기능 - 이상하게 흥분됩니다. – inspectorG4dget