[python] 목록이 비어 있는지 어떻게 확인합니까?

예를 들어, 다음을 통과 한 경우 :

a = []

a비어 있는지 확인하려면 어떻게합니까 ?



답변

if not a:
  print("List is empty")

공란암시 적 부울 을 사용하는 list것은 꽤 파이썬입니다.


답변

pythonic 방법은 PEP 8 스타일 가이드 ( Yes 는“권장”을 의미 하고 No 는“권장하지 않음 ”을 의미)에서 제공합니다.

시퀀스 (문자열, 목록, 튜플)의 경우 빈 시퀀스가 ​​거짓이라는 사실을 사용하십시오.

Yes: if not seq:
     if seq:

No:  if len(seq):
     if not len(seq):

답변

나는 그것을 명시 적으로 선호한다 :

if len(li) == 0:
    print('the list is empty')

이렇게 li하면 시퀀스 (목록) 인 것이 100 % 명확 하고 크기를 테스트하려고합니다. 내 문제 는 부울 변수 인 if not li: ...잘못된 인상을주는 것 li입니다.


답변

이것은 “python test empty array”및 유사한 쿼리에 대한 첫 번째 Google 히트이며 다른 사람들은 목록을 넘어서 질문을 일반화하는 것처럼 보이므로 많은 사람들이 다른 유형의 시퀀스에 대한 경고를 추가 할 것이라고 생각했습니다. 사용할 수 있습니다.

NumPy 배열에는 다른 방법이 작동하지 않습니다

NumPy 배열에는주의해야합니다. 왜냐하면 lists 또는 다른 표준 컨테이너에 대해 잘 작동하는 다른 메소드는 NumPy 배열에 실패하기 때문입니다. 나는 왜 아래에 설명하지만 간단히 말해서 선호하는 방법 을 사용하는 것 size입니다.

“pythonic”방식이 작동하지 않습니다 : 1 부

NumPy와가의 배열에 배열을 캐스팅하려고하기 때문에 “파이썬”방법은 NumPy와 배열 실패 bool의, 그리고 if x시도는 그 모든 평가 bool집계 진리 값의 몇 가지 종류의 한 번에들. 그러나 이것은 말이되지 않으므로 다음을 얻습니다 ValueError.

>>> x = numpy.array([0,1])
>>> if x: print("x")
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

“pythonic”방식이 작동하지 않습니다 : 2 부

그러나 적어도 위의 경우는 실패했다고 알려줍니다. 정확히 하나의 요소를 가진 NumPy 배열이 if발생하면 오류가 발생하지 않는다는 의미에서 명령문이 “작동”합니다. 그러나 한 요소가 0(또는 0.0, 또는 False…) 인 경우 if명령문은 다음과 같이 부정확하게됩니다 False.

>>> x = numpy.array([0,])
>>> if x: print("x")
... else: print("No x")
No x

그러나 분명히 x존재하며 비어 있지 않습니다! 이 결과는 당신이 원하는 것이 아닙니다.

를 사용하면 len예기치 않은 결과가 발생할 수 있습니다

예를 들어

len( numpy.zeros((1,0)) )

배열에 요소가없는 경우에도 1을 반환합니다.

numpythonic 방법

SciPy FAQ에 설명 된대로 NumPy 배열을 알고있는 모든 경우에 올바른 방법은 다음을 사용하는 것입니다 if x.size.

>>> x = numpy.array([0,1])
>>> if x.size: print("x")
x

>>> x = numpy.array([0,])
>>> if x.size: print("x")
... else: print("No x")
x

>>> x = numpy.zeros((1,0))
>>> if x.size: print("x")
... else: print("No x")
No x

그것이 list배열인지, NumPy 배열인지 또는 다른 것이 있는지 확실하지 않은 경우이 방법을 @dubiousjim이 제공하는 답변 과 결합하여 각 유형에 올바른 테스트가 사용되도록 할 수 있습니다. “pythonic”은 아니지만 NumPy가 의도적으로 pythonicity를 최소한 깨뜨린 것으로 밝혀졌습니다.

입력이 비어 있는지 확인하는 것 이상을 수행하고 인덱싱 또는 수학 연산과 같은 다른 NumPy 기능을 사용하는 경우 입력 NumPy 배열 만드는 것이 더 효율적일 것입니다 . 이 작업을 신속하게 수행 할 수있는 몇 가지 유용한 기능이 있습니다 numpy.asarray. 가장 중요 합니다. 이것은 입력을 취하거나 이미 배열 인 경우 아무것도하지 않거나 목록, 튜플 등의 경우 입력을 배열로 래핑하고 선택적으로 선택한로 변환합니다 dtype. 따라서 가능할 때마다 매우 빠르며 입력이 NumPy 배열이라고 가정 할 수 있습니다. 배열로 변환해도 현재 범위를 벗어나지 않기 때문에 일반적으로 동일한 이름 만 사용합니다 .

x = numpy.asarray(x, dtype=numpy.double)

이렇게하면 x.size이 페이지에 표시된 모든 경우에 확인이 작동합니다.


답변

목록이 비어 있는지 확인하는 가장 좋은 방법

예를 들어, 다음을 통과 한 경우 :

a = []

가 비어 있는지 어떻게 확인합니까?

짧은 답변:

부울 컨텍스트에 목록을 배치하십시오 (예 : if또는 while문). False비어 있는지 여부 를 테스트 합니다 True. 예를 들면 다음과 같습니다.

if not a:                           # do this!
    print('a is an empty list')

PEP 8

파이썬의 표준 라이브러리에있는 파이썬 코드를위한 공식 파이썬 스타일 가이드 인 PEP 8 은 다음과 같이 주장합니다.

시퀀스 (문자열, 목록, 튜플)의 경우 빈 시퀀스가 ​​거짓이라는 사실을 사용하십시오.

Yes: if not seq:
     if seq:

No: if len(seq):
    if not len(seq):

표준 라이브러리 코드는 가능한 성능 있고 정확해야합니다. 그러나 왜 그런가, 왜 우리는이 지침이 필요한가?

설명

파이썬을 처음 접하는 숙련 된 프로그래머가 다음과 같은 코드를 자주 봅니다.

if len(a) == 0:                     # Don't do this!
    print('a is an empty list')

그리고 게으른 언어 사용자는 다음과 같이 유혹 할 수 있습니다.

if a == []:                         # Don't do this!
    print('a is an empty list')

이들은 다른 언어로 정확합니다. 그리고 이것은 파이썬에서 의미 적으로 정확합니다.

그러나 파이썬은 불리언 강제를 통해 목록 객체의 인터페이스에서 직접 이러한 의미를 지원하기 때문에 비피 토닉으로 간주합니다.

로부터 문서 (그리고 참고 빈리스트의 구체적 포함, []) :

기본적으로 객체는 클래스 가 객체와 함께 호출 될 때 반환 하는 메서드 나 0 __bool__()을 반환 하는 메서드를 정의하지 않는 한 true로 간주됩니다 . 다음은 거짓으로 간주되는 대부분의 내장 객체입니다.False__len__()

  • false로 정의 된 상수 : NoneFalse.
  • 모든 숫자 유형의 제로 : 0, 0.0, 0j, Decimal(0),Fraction(0, 1)
  • 빈 시퀀스와 컬렉션 : '', (), [], {}, set(),range(0)

그리고 데이터 모델 문서 :

object.__bool__(self)

진실 가치 테스트 및 기본 제공 작업을 구현하기 위해 호출됩니다 bool(). False또는 을 반환해야합니다 True. 이 메소드가 정의되지 않은 경우이 메소드가 정의 된
__len__()경우 호출되며 결과가 0이 아닌 경우 오브젝트는 참으로 간주됩니다. 클래스가 __len__()
nor를 정의하지 않으면 __bool__()모든 인스턴스가 true로 간주됩니다.

object.__len__(self)

내장 함수를 구현하기 위해 호출됩니다 len(). 객체의 길이, 정수> = 0을 반환해야합니다. 또한 __bool__()메서드를 정의하지 않고 __len__()메서드가 0을 반환 하는 객체 는 부울 컨텍스트에서 false로 간주됩니다.

그래서 이것 대신에 :

if len(a) == 0:                     # Don't do this!
    print('a is an empty list')

아니면 이거:

if a == []:                     # Don't do this!
    print('a is an empty list')

이 작업을 수행:

if not a:
    print('a is an empty list')

Pythonic을 수행하면 일반적으로 성능이 향상됩니다.

돈을 지불합니까? (동일한 작업을 수행하는 데 걸리는 시간이 짧을수록 좋습니다.)

>>> import timeit
>>> min(timeit.repeat(lambda: len([]) == 0, repeat=100))
0.13775854044661884
>>> min(timeit.repeat(lambda: [] == [], repeat=100))
0.0984637276455409
>>> min(timeit.repeat(lambda: not [], repeat=100))
0.07878462291455435

스케일의 경우, 함수를 호출하고 빈 목록을 작성하고 리턴하는 비용이 있습니다. 위에서 사용한 공허 점검 비용에서 차감 할 수 있습니다.

>>> min(timeit.repeat(lambda: [], repeat=100))
0.07074015751817342

우리는 볼 내장 기능 길이에 대한 검사 len에 비해 0 또는 빈 목록에 대해 확인이 훨씬 덜 확대됨에 설명 된대로 언어의 내장 구문을 사용하는 것보다.

왜?

에 대한 len(a) == 0검사 :

먼저 파이썬은 전역을 검사하여 len그림자가 있는지 확인해야합니다 .

그런 다음 함수, load를 호출하고 0Python에서 C 대신 등식 비교를 수행해야합니다.

>>> import dis
>>> dis.dis(lambda: len([]) == 0)
  1           0 LOAD_GLOBAL              0 (len)
              2 BUILD_LIST               0
              4 CALL_FUNCTION            1
              6 LOAD_CONST               1 (0)
              8 COMPARE_OP               2 (==)
             10 RETURN_VALUE

그리고 [] == []불필요한 목록을 작성하고 다시 파이썬의 가상 머신에서 비교 작업을 수행해야합니다 (C가 아닌)

>>> dis.dis(lambda: [] == [])
  1           0 BUILD_LIST               0
              2 BUILD_LIST               0
              4 COMPARE_OP               2 (==)
              6 RETURN_VALUE

“Pythonic”방식은 목록의 길이가 객체 인스턴스 헤더에 캐시되므로 훨씬 간단하고 빠른 검사입니다.

>>> dis.dis(lambda: not [])
  1           0 BUILD_LIST               0
              2 UNARY_NOT
              4 RETURN_VALUE

C 소스 및 문서의 증거

PyVarObject

이것은 필드 PyObject를 추가 하는 확장입니다 ob_size. 길이 개념이있는 객체에만 사용됩니다. 이 유형은 종종 Python / C API에 나타나지 않습니다. PyObject_VAR_HEAD매크로 의 확장으로 정의 된 필드에 해당합니다 .

Include / listobject.h 의 c 소스에서 :

typedef struct {
    PyObject_VAR_HEAD
    /* Vector of pointers to list elements.  list[0] is ob_item[0], etc. */
    PyObject **ob_item;

    /* ob_item contains space for 'allocated' elements.  The number
     * currently in use is ob_size.
     * Invariants:
     *     0 <= ob_size <= allocated
     *     len(list) == ob_size

의견에 대한 답변 :

나는이와 같은 자사의 꽤 추한하지만 비어 있지 않은 경우에도 마찬가지입니다 것을 지적 할 l=[]다음 %timeit len(l) != 090.6 ns의 ± 8.3 ns의, %timeit l != []55.6 ns의 ± 3.09, %timeit not not l38.5 ns의 ± 0.372. 그러나 not not l세 배의 속도에도 불구하고 누구나 즐길 수있는 방법은 없습니다 . 어리석어 보인다. 그러나 속도가 빠릅니다
. 문제 if l:가 충분하지만 놀랍게도 %timeit bool(l)101 ns ± 2.64 ns를 생성 하기 때문에 문제가 timeit로 테스트되고 있다고 가정합니다 . 흥미롭게도이 형벌 없이는 강압 할 수있는 방법이 없습니다. %timeit l전환이 발생하지 않으므로 쓸모가 없습니다.

IPython 매직 %timeit은 여기서 완전히 쓸모없는 것은 아닙니다.

In [1]: l = []

In [2]: %timeit l
20 ns ± 0.155 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)

In [3]: %timeit not l
24.4 ns ± 1.58 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [4]: %timeit not not l
30.1 ns ± 2.16 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

not여기서 추가 할 때마다 약간의 선형 비용이 있음을 알 수 있습니다. 우리는 ceteris paribus 의 비용, 즉 다른 모든 것이 가능한 한 최소화되는 곳 을보고 싶습니다 .

In [5]: %timeit if l: pass
22.6 ns ± 0.963 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [6]: %timeit if not l: pass
24.4 ns ± 0.796 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [7]: %timeit if not not l: pass
23.4 ns ± 0.793 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

이제 빈 목록에 대한 사례를 살펴 보겠습니다.

In [8]: l = [1]

In [9]: %timeit if l: pass
23.7 ns ± 1.06 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [10]: %timeit if not l: pass
23.6 ns ± 1.64 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [11]: %timeit if not not l: pass
26.3 ns ± 1 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

여기에서 볼 수있는 것은 실제 bool상태 확인이나 목록 자체에 전달하는지 여부와 거의 차이가 없으며 목록을 제공하는 것이 더 빠르다는 것입니다.

파이썬은 C로 작성되었습니다. C 레벨에서 논리를 사용합니다. 파이썬으로 쓰는 것은 느려질 것입니다. 그리고 파이썬에 직접 내장 된 메커니즘을 사용하지 않으면 수십 배 느려질 것입니다.


답변

실제 값 테스트에서는 빈 목록 자체가 거짓으로 간주됩니다 ( 파이썬 문서 참조 ).

a = []
if a:
     print "not empty"

@ 대런 토마스

편집 : 빈 목록을 False로 테스트하는 것에 대한 또 다른 요점 : 다형성은 어떻습니까? 리스트 인리스트에 의존해서는 안됩니다. 오리처럼 ck 것입니다-요소가 없을 때 duckCollection을“False ”로 가져 오는 방법은 무엇입니까?

귀하의 duckCollection 구현해야한다 __nonzero__또는 __len__는 A, 그래서 만약이 : 문제없이 작동합니다.


답변

Patrick의 (허용 된) 대답 은 옳 if not a:습니다. 올바른 방법입니다. Harley Holcombe의 답변 은 이것이 PEP 8 스타일 가이드에 있다는 것이 옳습니다. 그러나 어떤 대답도 설명 할 수없는 이유는 개인적으로 루비 사용자 나 그 밖의 사람들에게 명시 적이거나 혼란스럽지 않다고 생각하더라도 관용구를 따르는 것이 좋은 생각입니다.

파이썬 코드와 파이썬 커뮤니티에는 매우 강력한 관용구가 있습니다. 이러한 관용구를 따르면 파이썬을 경험 한 사람이라면 누구나 쉽게 코드를 읽을 수 있습니다. 그리고 당신이 그 관용구를 위반하면, 그것은 강한 신호입니다.

그것은 그 사실 if not a:에서 빈 목록을 구분하지 않습니다 Nonefalsey와 스칼라의 역할을, 또는 숫자 0, 또는 빈 튜플, 또는 빈 사용자가 만든 수집 유형 또는 빈 사용자가 생성되지-매우 수집 유형 또는 단일 요소 NumPy와 배열을 값 등을 명시해야합니다. 그리고 그 경우에, 당신은 알고 무엇을 당신이 정확하게 테스트 할 수 있도록 명시 적으로 약 싶어요. 예를 들어, if not a and a is not None:“없음을 제외한 모든 것” if len(a) != 0:은 “빈 시퀀스 만 – 시퀀스 이외의 것은 오류입니다”등을 의미합니다. 정확하게 테스트하려는 대상을 테스트하는 것 외에도이 테스트가 중요하다는 것을 독자에게 알립니다.

그러나 당신이 분명하게 언급 할 것이 없다면 if not a:, 독자를 오도하는 것 이외의 것이 있습니다. 중요하지 않은 중요한 것을 신호하고 있습니다. (당신은 또한 코드가 덜 유연하고, 또는 느리게, 또는 무엇이든,하지만 모든 덜 중요합니다. 할 수있다) 그리고 당신이 경우 습관적으로 이 같은 독자를 오도 당신이 때, 어떻게 구분을 할 필요가, 주목 인해를 통과 것 당신은 당신의 코드 전체에 “늑대를 울고있다”.