A와 A가 없음이 아닌 경우 :


154

사용해도 되나요:

if A:

대신에

if A is not None:

후자는 너무 장황 해 보인다. 차이가 있습니까?

답변:


149

진술

if A:

호출하고 A.__nonzero__()( 특수 메서드 이름 설명서 참조 ) 해당 함수의 반환 값을 사용합니다. 요약은 다음과 같습니다.

object.__nonzero__(self)

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

반면에

if A is not None:

비교 만을 기준 A으로 None그 동일한인지 여부를 확인한다.


4
그렇게 A is not None할 일이 많이 적은 작업이 있기 때문에 빠른
존 라 Rooy

40
@gnibbler 내 테스트에 따르지 않습니다. if object(): pass루프 당 ~ 0.130 usec if object() is not None: pass이고 ~ 0.135 usec입니다. 어쨌든 성능을 사용하여이 두 가지 중 하나를 선택 하지 말고 동등하지 않기 때문에 작동 방식의 차이점을 살펴보십시오 .
Lauritz V. Thaulow

1
@gnibbler if A is not None는 비교하기 때문에 느리게 보이며 내장 싱글 톤 None을 중개 단계로 로드하여 비교해야합니다 A(을보십시오 dis.dis()). 내가 틀렸지 만 if A:진실이 아닌 진실의 가치를 시험하고 싶어하는 즉시 더 효율적인 것처럼 나를 교정하십시오 None.
cedbeu

2
@cedbeu, A의 가치에 의존하는 것 같습니다. 지금 테스트 한 python -m timeit -s"a=0" "if a: pass" "else: pass"것보다 빠르지 python -m timeit -s"a=0" "if a is None: pass" "else: pass"python -m timeit -s"a=1" "if a: pass" "else: pass"느립니다. 플랫폼에 따라 다를 수 있습니다. 같은 결과를 얻으십시오
John La Rooy

2
@cedbeu, Python3에서는 모두 훨씬 빠르지 만 is None테스트는 실제로 가장 느 렸습니다 . pypy에서 그들은 모두 똑같이 측정했습니다 :)
John La Rooy

51

PEP8 로 작성된 :

  • 없음 과 같은 싱글 톤과의 비교 는 항상 등호 연산자가 아닌 'is'또는 'is not'으로 수행해야합니다 .

    또한 "x가 None이 아닌 경우"를 의미 할 때 "if x"를 쓰지 않도록주의하십시오. 예를 들어 기본값이 None 인 변수 또는 인수가 다른 값으로 설정되어 있는지 테스트 할 때. 다른 값에는 부울 컨텍스트에서 false 일 수있는 유형 (예 : 컨테이너)이있을 수 있습니다!


7
그러나 이것은 명확하지 않으며 OP에 응답하지 않습니다. PEP 로의 자동 리디렉션이 항상 좋은 대답은 아닙니다. 종종 singleton으로 아이덴티티 테스트에 관심이 없지만 None진실 값 확인에만 관심이 있습니다. 이 경우, if A:(A을보다 효율적으로 보인다 dis.dis()내장을로드하는 추가 단계가, None와,와 비교 if A is not None:만이 있지만, jump_if다른 경우).
cedbeu

29
if x: #x is treated True except for all empty data types [],{},(),'',0 False, and None

그래서 그것은 같지 않습니다

if x is not None # which works only on None

17

적절한 결과가 없으면 많은 함수가 None을 반환합니다. 예를 들어, .first()결과에 행이 없으면 SQLAlchemy 쿼리의 메서드는 None을 반환합니다. 0을 리턴 할 수있는 값을 선택하고 실제로 0인지 또는 쿼리에 결과가 전혀 없는지 알아야한다고 가정하십시오.

일반적인 관용구는 함수 또는 메서드의 선택적 인수에 기본값 None을 부여한 다음 해당 값이 None인지 테스트하여 값이 지정되었는지 확인하는 것입니다. 예를 들면 다음과 같습니다.

def spam(eggs=None):
    if eggs is None:
        eggs = retrievefromconfigfile()

그것을 다음과 비교하십시오 :

def spam(eggs=None):
    if not eggs:
        eggs = retrievefromconfigfile()

전화 할 경우 후자에 무슨 일이 spam(0)spam([])? 함수는 (잘못된) 값을 전달하지 않았 음을 감지 eggs하고 기본값을 계산합니다. 아마 당신이 원하는 것이 아닐 것입니다.

또는 "주어진 계정에 대한 거래 목록을 반환"과 같은 방법을 상상해보십시오. 계정이 없으면 None을 반환 할 수 있습니다. 이것은 비어있는 목록을 반환하는 것과 다릅니다 ( "이 계정은 존재하지만 기록 된 트랜잭션이 없음"을 의미 함).

마지막으로 데이터베이스로 돌아갑니다. NULL과 빈 문자열 사이에는 큰 차이가 있습니다. 빈 문자열은 일반적으로 "여기에 값이 있으며 그 값은 전혀 없습니다"라고 말합니다. NULL은 "이 값을 입력하지 않았습니다"라고 말합니다.

각각의 경우에을 사용하려고합니다 if A is None. "False로 캐스트되는 모든 값"뿐만 아니라 특정 값 (없음)을 확인하고 있습니다.


10

그들은 매우 다른 일을 합니다.

아래의 검사 A는 값을 제외하고 무엇이든이있는 경우 False, [], None, ''0. A 의 을 확인합니다 .

if A:

아래는 A가 없음과 다른 객체인지 확인합니다. A와 None 의 참조 (메모리 주소)를 확인하고 비교합니다 .

if A is not None:

업데이트 : 추가 설명

많은 경우 두 사람이 같은 일을하는 것처럼 보이므로 많은 사람들이 서로 바꿔서 사용합니다. 정말 나쁜 생각입니다. 두 사람이 동일한 결과를 얻는 이유는 인턴 또는 다른 것과 같은 인터프리터 / 컴파일러의 최적화로 인해 순수한 우연의 일치 로 여러 번 발생합니다 .

이러한 최적화를 염두에두고 동일한 값의 정수와 문자열은 동일한 메모리 공간을 사용합니다. 아마도 두 개의 개별 문자열이 동일한 것처럼 작동하는 이유를 설명합니다.

> a = 'test'
> b = 'test'
> a is b
True
> a == b
True

다른 것들도 똑같이 동작하지 않습니다 ..

> a = []
> b = []
> a is b
False
> a == b
True

두 목록에는 분명히 자신의 기억이 있습니다. 놀랍게도 튜플은 문자열처럼 행동합니다.

> a = ()
> b = ()
> a is b
True
> a == b
True

아마도 이것은 튜플이 변경되지 않도록 보장되기 때문에 동일한 메모리를 재사용하는 것이 좋습니다.

결론은 우연의 일치에 의존수 없다는 것 입니다. 오리처럼 because다고해서 오리라는 의미는 아닙니다. 사용 is하고 ==당신이 정말로 확인하려는 작업에 따라 달라집니다. is우리가 종종 넘어가는 산문과 같은 읽기 때문에 이러한 것들을 디버깅하기 가 어려울 수 있습니다 .


None단일 톤이며 구현 세부 정보가 아닙니다 (int 또는 string interning과 달리). 나는 당신이 무엇을 의미하는지 잘 모르겠습니다.
Lev Levitsky

@LevLevitsky 내 요점은 인턴 None과 다르게 int또는 인트로 str인해 작동 하지 않습니다 . 내 요점은이다 is==다른 것을 확인하고 있습니다; 첫 번째는 메모리 주소를 확인하고 두 번째는 메모리 주소의 내용을 확인합니다.
Pithikos

@LevLevitsky 좀 더 소화하기 쉽게 내 답변을 편집했습니다.
Pithikos

7

if A: A가 0, False, 빈 문자열, 빈 목록 또는 없음 인 경우 false로 표시되어 원하지 않는 결과가 발생할 수 있습니다.


1
그리고 빈 목록, 빈 세트, 빈 튜플 등과 같은 다른 많은 값들도 있습니다. 본질적으로 docs.python.org/3/library/stdtypes.html#truth-value-testing에 따라 진실 이 아닌 모든 것 .
jarmod

6

내가 본 대부분의 가이드는 당신이 사용해야한다고 제안합니다.

만약:

더 구체적인 이유가 없다면

약간의 차이가 있습니다. 비어있는 목록 또는 0과 같이 False를 반환하는 None 이외의 값이 있으므로 실제로 테스트 대상이 무엇인지 생각해보십시오.


5

None은 일반적으로 초기화되지 않은 변수를 지정하는 Python의 특별한 값입니다 . A에이 특정 값이 없는지 테스트하려면 다음을 사용하십시오.

if A is not None

Falsey 값은 Python의 특수 객체 클래스입니다 (예 : false, []). A가 거짓인지 테스트하려면 다음을 사용하십시오.

if not A

따라서 두 표현은 같지 않으며 동의어로 취급하지 않는 것이 좋습니다.


PS None도 거짓이므로 첫 번째 표현은 두 번째 표현을 의미합니다. 그러나 두 번째는 None 이외의 다른 잘못된 값을 다룹니다. 자 ... A에서 없음 이외의 다른 잘못된 값을 가질 수없는 경우 첫 번째 표현식을 두 번째 표현식으로 바꿀 수 있습니다.


당신이 틀린 것은 아니지만 이 답변은 이미 이것을 다루고 있습니다.
Makoto

Boh, 당신이 마음에 들지 않으면 downvote를 제거하도록 요청하고 싶습니다. 내 대답은 다른 모든 것과 동등하지만 아마도 당신이 언급 한 것과는 덜 다르지만 다른 관점에서 제시되며 누군가를 이해하는 것이 더 쉬울 수 있습니다. 또한, 내가 downvote를 볼 때 나는 잘못된 대답을 가정합니다 ... 당신이 인정하는 것은 아닙니다.
mircealungu

글쎄, 그 가정은 불완전합니다. 잘못되었거나 단순히 유용하지 않을 수 있습니다. 내가 말한대로 답변이 이미 다루어 졌기 때문에 나는 그것이 유용하다고 확신하지 않습니다.
Makoto

4

상황에 따라 다릅니다.

나는 일종의 컬렉션이 될 if A:것으로 기대할 때 사용 A하며 컬렉션이 비어 있지 않은 경우에만 블록을 실행하고 싶습니다. 이렇게하면 호출자가 비어 있거나없는 잘 동작하는 컬렉션을 전달하고 예상 한대로 수행 할 수 있습니다. 또한 코드 실행에 편리한 블록 실행을 허용 NoneFalse억제합니다.

OTOH, 내가 기대한다면 A어떤 완전히 임의의 객체 수 있지만,이 디폴트로 수 있었던 None그때, 항상 사용하는 if A is not None코드를 호출하면 의도적으로 빈 수집, 빈 문자열 또는 0 값 숫자 형식에 대한 참조를 통과 한 수로, 또는 boolean False또는 boolean 컨텍스트에서 false 인 클래스 인스턴스.

그리고 다른 한편으로, A좀 더 구체적인 것 (예 : 클래스를 호출 할 클래스의 인스턴스)이 될 것으로 예상 되지만 기본값으로 설정되었을 수 있으며 None기본 부울 변환은 클래스의 속성 모든 하위 클래스에 적용하는 것을 신경 쓰지 않으면 if A:손가락을 추가로 12 자 입력하는 끔찍한 부담을 덜기 위해 사용 합니다.


3

라는 파일을 작성 test.py하여 통역사에서 실행했습니다. 장면 뒤에서 상황이 어떻게 진행되고 있는지 테스트하기 위해 원하는 것을 변경할 수 있습니다.

import dis

def func1():

    matchesIterator = None

    if matchesIterator:

        print( "On if." );

def func2():

    matchesIterator = None

    if matchesIterator is not None:

        print( "On if." );

print( "\nFunction 1" );
dis.dis(func1)

print( "\nFunction 2" );
dis.dis(func2)

이것이 어셈블러 차이점입니다.

출처:

>>> import importlib
>>> reload( test )

Function 1
  6           0 LOAD_CONST               0 (None)
              3 STORE_FAST               0 (matchesIterator)

  8           6 LOAD_FAST                0 (matchesIterator)
              9 POP_JUMP_IF_FALSE       20

 10          12 LOAD_CONST               1 ('On if.')
             15 PRINT_ITEM
             16 PRINT_NEWLINE
             17 JUMP_FORWARD             0 (to 20)
        >>   20 LOAD_CONST               0 (None)
             23 RETURN_VALUE

Function 2
 14           0 LOAD_CONST               0 (None)
              3 STORE_FAST               0 (matchesIterator)

 16           6 LOAD_FAST                0 (matchesIterator)
              9 LOAD_CONST               0 (None)
             12 COMPARE_OP               9 (is not)
             15 POP_JUMP_IF_FALSE       26

 18          18 LOAD_CONST               1 ('On if.')
             21 PRINT_ITEM
             22 PRINT_NEWLINE
             23 JUMP_FORWARD             0 (to 26)
        >>   26 LOAD_CONST               0 (None)
             29 RETURN_VALUE
<module 'test' from 'test.py'>

2

전자는 더 파이썬 적이지만 (더 나은 이데올로기 코드) A가 False이면 (아무것도 아님) 블록을 실행하지 않습니다.


7
-1. @klesh가 언급했듯이 PEP8은을 사용한다고 말합니다 is/is not None. PEP8 다음은 Pythonic입니다. 두 테스트 외에는 다릅니다 .
JCotton

1

파이썬> = 2.6,

우리가 다음과 같이 쓰면

if A:

다음과 같이 경고를 생성합니다.

FutureWarning :이 방법의 동작은 다음 버전에서 변경 될 것입니다. 대신 특정 'len (elem)'또는 'elem is not None'테스트를 사용하십시오.

그래서 우리는 사용할 수 있습니다

if A is not None:
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.