2009-11-03 3 views
2

일부 기능에 대한 입력 개체가 특정 구조를 준수하는지 확인할 수있는 간단한 방법이 있습니까? 예를 들어, 정수 목록 인 문자열 키와 값의 사전 만 원합니다.python의 개체가 특정 구조를 준수하는지 확인

한 가지 방법은 객체에 전달하는 재귀 함수를 작성하는 것입니다. 반복하는 반복 함수는 각 레벨에서 예상 한 것과 같습니다. 하지만 파이썬에서보다 더 우아한 방법이 있어야한다고 생각합니다.

답변

3

유형 검사의 모든 생각이 세상을 마음 속에 그리고 상호 작용의 파이썬의 방식 때문에 완전히 외국인이기 때문에 왜, 파이썬 유형을 확인하는 "우아한 방법"을 제공하기 위해 기대! 일반적으로 파이썬에서는 오리 타이핑을 사용합니다. "정수"는 똑같이 int, long, gmpy.mpz 일 수 있습니다 - 유형은 모두 동일한 코어 서명을 구현한다는 점만 제외하면 서로 관계가 없습니다 ... "a dict"는 매핑의 구현 일 수 있습니다.

"추상 기본 클래스"의 새로운 개념은 덕 타이핑을 구현하고 확인하는 체계적인 방법을 제공하며 3.0 이상의 기능을 사용하면 이러한 검사 시스템과 상호 작용할 수 있습니다 (써드 파티, 파이썬은 가까운 장래에 그러한 시스템을 채택하지 않기 때문에). 예를 들어, this recipe은 기능 주석에 기반하여 "다소 비슷하지만 아주"형식 검사를 수행하는 3.0 이상의 방법을 제공합니다. 그러나 원하는만큼 깊숙한 곳으로가는 것은 의심의 여지가 있지만 기능 주석을 작성하는 것은 초기 단계입니다. 우리 중 대부분은 Pythonistas가 그러한 체크에 대해 거의 갈망하지 않는다고 느끼기 때문에 실제적으로 대신 코드 대신 이러한 기념비적 인 시스템을 구현할 수는 없을 것입니다.

+1

@ Alex Martelli : 앤드류 (Andrew)는 지난 밤에 내 것과 비슷한 질문을하고 있다고 생각합니다. 그리고, 아니, 아마 Pythonic이 아니지만, 당연한 일을 멈추게하는 프로그램을 디버그하는 데 도움이 될 것입니다. 나는 오류의 원인을 보려고 노력하고 오류의 결과를보기 위해 도구를 가지고 있지 않은 코드를 쳐다보아야한다는 것은 피피 닉이 아니라고 주장 할 수있다. – behindthefall

+0

@ Alex Martelli : Alex, 인터프리터는 모든 사물의 구조를 잠시 알 수 있습니까? 이 정보를 (선택적으로) 저장하고 덤프하는 방법이 있습니까? 이미 가까이에있는 "기념비적 인 시스템"이 있습니다! ;-) – behindthefall

+0

또 다른 문제는 예를 들어이 dict (string : list (int) *)와 같이 원하는 구조를 지정할 수 있으면 함수 자체에 다양한 입력을 받아 들일 수 있다는 것입니다. 각 입력을 원하는 것으로 변환하는 방법. list (float, list (int))? float를 문자열에 매핑하고 외부 목록을 dict에 매핑합니다. 코드 자체는 하나의 구조를 취하지 만 메타 데이터는 메소드 호출, 메소드의 실제 코드 앞에 – Andrew

0

파이썬은 올바르게 작동하는 것을 강조하므로, 사용자가 가서 올바른 데이터를 제공하도록 라이브러리 사용자를 신뢰하면 가장 좋은 방법은 assert입니다. 당신이해야하는 경우에, 예외는 일어나십시오; 그건 당신의 고객이 당신의 문서화 문자열을 읽지 못했기 때문입니다. 이 같은 귀하의 경우에는

, 뭔가 :

def myfunction(arrrrrgs): 
    assert issubclass(dict, type(arrrrrgs)), "Need a dictionary!" 
    for key in arrrrrgs: 
     assert type(key) is str, "Need a string!" 
     val = arrrrrgs[key] 
     assert type(val) is list, "Need a list!" 

등.

정말로 노력하지 않아도되고 문서화 문자열에서 자신을 명확하게 표현하면 프로그램이 파열되거나 늦은 밤 디버거를 안내하기 위해 잘 배치 된 예외를 throw 할 수 있습니다.

1

간단한 대답, 아니요, 자신 만의 기능을 만들어야합니다.

긴 답변 : 당신이 요구하는 것을 수행 할 파이썬이 아닙니다. 몇 가지 특별한 경우가있을 수 있습니다 (예 : xmlrpc에 dict을 마샬링).하지만 개체가 문서화 된 것과 같이 작동한다고 가정합니다. 그렇지 않다면 AttributeError 버블을 버리십시오. 강제 값을 사용하는 것이 좋으면 str()int()을 사용하여 값을 변환하십시오. 그들은 후에 __str__, __add__ 등을 구현하여 int/str의 자손이 아니지만 여전히 사용할 수있게합니다.

def dict_of_string_and_ints(obj): 
    assert isinstance(obj, dict) 
    for key, value in obj.iteritems(): # py2.4 
    assert isinstance(key, basestring) 
    assert isinstance(value, list) 
    assert sum(isinstance(x, int) for x in value) == len(list) 
+0

+1 : 올바른 구조가 아니라면 KeyError 또는 IndexError 예외가 발생합니다. 너는 무엇을 더 필요로 하는가? –

0

나는 촬영을하고 더 일반적인 + 우아한 방법으로 당신을 위해 그런 일을 할 수있는 도우미 함수 제시 할 것이다 : 코멘트는 사용의 샘플을 설명

def check_type(value, type_def): 
    """ 
    This validates an object instanct <value> against a type template <type_def> 
    presented as a simplified object. 
    E.g. 
    if value is list of dictionaries that have string values as key and integers 
    as values: 
    >> check_type(value, [{'':0}]) 
    if value is list of dictionaries, no restriction on key/values 
    >> check_type(value, [{}]) 
    """ 
    if type(value) != type(type_def): 
     return False 
    if hasattr(value, '__iter__'): 
     if len(type_def) == 0: 
      return True 
     type_def_val = iter(type_def).next() 
     for key in value: 
      if not check_type(key, type_def_val): 
       return False 
     if type(value) is dict: 
      if not check_type(value.values(), type_def.values()): 
       return False 
    return True 

,하지만 당신은 항상 갈 수있다 꽤 깊다.

>>> check_type({1:['a', 'b'], 2:['c', 'd']}, {0:['']}) 
True 
>>> check_type({1:['a', 'b'], 2:['c', 3]}, {0:['']}) 
False 

P.한 번에 하나씩 튜플 유효성 검사 (예 : ([], '', {0 : 0})에 대한 유효성 검사가 필요하면 지금 수정하십시오.)

관련 문제