파이썬에서 변수가 사전인지 확인하는 방법?


214

파이썬에서 변수가 사전인지 어떻게 확인합니까?

예를 들어, 사전을 찾을 때까지 사전의 값을 반복하고 싶습니다. 그런 다음 찾은 것을 반복하십시오.

dict = {'abc': 'abc', 'def': {'ghi': 'ghi', 'jkl': 'jkl'}}
for k, v in dict.iteritems():
    if ###check if v is a dictionary:
        for k, v in v.iteritems():
            print(k, ' ', v)
    else:
        print(k, ' ', v)

또한 stackoverflow.com/questions/378927/… (위의 사본으로 표시됨).
NPE


40
아니요, 같은 질문이 아닙니다. 이 질문에 대한 답변과 여기에 나열된 다른 질문에 대한 답변은 모두 실질적으로 동일한 정보를 포함합니다. 그러나 "변수가 파이썬에서 사전인지 확인하는 방법"에 대한 대답은 "Use type () 또는 isinstance ()"입니다. 그러면 새로운 질문이 생겨서 type ()과 isinstance ()의 차이점은 무엇입니까? . 그러나 첫 번째 질문을하는 사람은 첫 번째 질문에 대답 할 때까지이를 알 수 없습니다. Ergo, 다른 질문은 사이트에서 질문을 찾을 때 중요합니다.

13
나는 @mbakeranalecta에 동의합니다. "변수가 파이썬에서 사전인지 확인하는 방법"에 대한 답을 찾고 왔습니다. 그리고 나는 "python에서 isinstance ()와 type ()의 차이점"에 대한 대답을 보지 못했을 것입니다.
lodebari

5
변수가 특히 사전인지 확인하려면을 사용해야합니다 isinstance(v, collections.abc.Mapping). 다시 말해, 이것은 "isinstance ()와 type ()의 차이점"의 정확한 복제본이 아닙니다.
Josh Kelley

답변:


279

서브 클래스 화 한 경우 작동 if type(ele) is dict하거나 사용할 수 있습니다 .isinstance(ele, dict)dict

d = {'abc':'abc','def':{'ghi':'ghi','jkl':'jkl'}}
for ele in d.values():
    if isinstance(ele,dict):
       for k, v in ele.items():
           print(k,' ',v)

70
일반적인 질문에 대한 정답은 다음과 같습니다 isinstance(ele, collections.Mapping). 그것은 작동 dict(), collections.OrderedDict()collections.UserDict(). 이 질문의 예는 Padriac의 답변이 작동하기에 충분하지만 일반적인 경우에는 충분하지 않습니다.
Alexander Ryzhov 2016 년

3
이 답변을 다운 투표했습니다. 왜냐하면 당신이 호출하려고하면 ele.items()왜 유형을 확인합니까? EAFP / 오리 타이핑 여기 작동, 단지 포장 for k,v in ele.items()에서 try...except (AttributeError, TypeError). 예외가 발생 하면 반복 할 수있는 결과 ele가 없습니다 items.
cowbert

@Padraic Cunningham 당신의 "가장 중요한 100 %"커스텀 클래스 1을 요구하는 가상의 최후의 사례는 1. items()iterable을 산출하기 위해 일어난 방법 2. 튜플. 이 시점에서 사용자 정의 객체는 이미 dict의 절반을 이미 구현했습니다. 나열된 코드의 목적을 위해 우리는 중첩 요소의 조건부 확장에만 관심을 기울였으며 사용자 정의 객체는 이미 구현했습니다. (@Alexander Ryzhov의 의견이 너무 일반적이라는 점을 비판하는 것은 약간 아이러니하지만 이제는 일반적인 경우를 제기합니다)
cowbert

1
@PadraicCunningham 나는 파이썬 안티 패턴에 익숙하지 않은 사람들에게 시작하는 것을 가르치고 싶지 않습니다. 파이썬 에는 명시 적 유형 검사 가 필요한 유스 케이스가 거의 없습니다. 대부분 잘못된 구현을 상속 ( '신 객체, 표준 라이브러리 / 언어 구문 무시 등)에서 비롯됩니다. 원래 질문 자체는 XY 문제입니다. OP가 유형을 확인해야하는 이유는 무엇입니까? 코드에 따르면 실제로 수행하려는 작업은 컬렉션의 항목이 컬렉션 처럼 동작 하는지 확인 하는 것입니다 ( items()중첩 된 반복 가능 항목을 생성하는 구현 ).
cowbert

4
@AlexanderRyzhov 왜 그 접근법을 답변으로 게시하지 않습니까? Josh Kelley 가 위에서 제안한 BTW에서 BTW collections.abc.Mapping는 동일하지만 collections.abcPython 3.3 이전에는 사용할 수 없다는 메모가 적합 할 수 있습니다 . collections.Mappingalias는 Python 3.6에서 계속 사용할 수 있지만 문서화되어 있지 않으므로 선호해야합니다 collections.abc.Maping.
Yushin Washio

5

파이썬에서 변수가 사전인지 어떻게 확인합니까?

이것은 훌륭한 질문이지만 가장 유력한 답변이 잘못된 추천으로 이어진다는 것은 불행한 일 type(obj) is dict입니다.

( dict변수 이름으로 도 사용해서는 안됩니다 . 내장 객체의 이름입니다.)

다른 사람이 가져 와서 사용할 코드를 작성하는 경우 직접 내장 된 dict을 사용한다고 가정하지 마십시오. 추정으로 인해 코드가 더 융통성이 없어지고이 경우 프로그램을 오류로 만들지 않는 숨겨진 버그를 쉽게 만들 수 있습니다. .

보다 유연하고 관용적 인 표현이있을 때 코드에서 유연하고 일관적인 표현을하지 않는 미래의 사용자를위한 정확성, 유지 관리 성 및 유연성을 위해 강력히 제안합니다.

is객체 식별 테스트입니다 . 상속을 지원하지 않으며 추상화를 지원하지 않으며 인터페이스를 지원하지 않습니다.

그래서 몇 가지 옵션을 제공 할 것입니다.

상속 지원 :

사용자가 자신의 DICT의 서브 클래스, 또는 공급하는 것이 할 수 있기 때문에, 내가 만드는 것이 첫 번째 추천 OrderedDict, defaultdict또는 Counter컬렉션이 모듈을 :

if isinstance(any_object, dict):

그러나 더 유연한 옵션이 있습니다.

지원 추상화 :

from collections.abc import Mapping

if isinstance(any_object, Mapping):

이를 통해 코드 사용자는의 하위 클래스를 포함하는 추상 매핑의 자체 사용자 지정 구현을 사용 dict하고 여전히 올바른 동작을 얻을 수 있습니다.

인터페이스를 사용하십시오

일반적으로 OOP 조언, "인터페이스 프로그램"을들을 수 있습니다.

이 전략은 파이썬의 다형성 또는 오리 타이핑을 활용합니다.

따라서 합리적인 폴백으로 인터페이스에 액세스하여 특정 예상 오류 ( AttributeError없음 .items및 호출 할 수없는 TypeError경우 items)를 잡으십시오.이 인터페이스를 구현하는 모든 클래스는 항목을 제공합니다 ( .iteritems()Python에서 사라졌습니다) 삼):

try:
    items = any_object.items()
except (AttributeError, TypeError):
    non_items_behavior(any_object)
else: # no exception raised
    for item in items: ...

아마도 이와 같은 덕 타이핑을 사용하면 너무 많은 오 탐지를 허용하는 데 너무 멀리 가고 있다고 생각할 수도 있습니다.이 코드의 목표에 따라 다를 수 있습니다.

결론

is표준 제어 흐름 유형을 확인 하는 데 사용하지 마십시오 . 사용은 isinstance같은 추상화 고려 Mapping또는 MutableMapping, 피하는 고려 유형 검사, 모두 직접 인터페이스를 사용하여.


3

OP는 시작 변수를 제외하지 않았으므로 완전성을 위해 항목을 사전으로 포함 할 수있는 사전을 처리하는 일반적인 경우를 처리하는 방법이 있습니다.

또한 위의 주석에서 사전을 테스트 하는 순수한 Python (3.8) 권장 방법 을 따르십시오 .

from collections.abc import Mapping

dict = {'abc': 'abc', 'def': {'ghi': 'ghi', 'jkl': 'jkl'}}

def parse_dict(in_dict): 
    if isinstance(in_dict, Mapping):
        for k, v in in_dict.items():
            if isinstance(v, Mapping):
                for k, v in v.items():
                    print(k, v)
            else:
                print(k, v)

parse_dict(dict)

dict.iteritems()파이썬 3에는 존재하지 않으므로 dict.items()대신 사용해야 합니다.
Arkelis

@Arkelis Oops, 방금 해당 부분을 복사 / 붙여 넣었습니다. 지적 해 주셔서 감사합니다. 이제 수정되었습니다.
CodeMantle
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.