본문 바로가기
개발/Python

if A 와 if A is not None

by MinorMan 2021. 1. 12.
반응형

<질문>

사용해도 되나요:

if A:

대신에

if A is not None:

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


<답변1>

진술

if A:

부를 것이다A.__nonzero__()(보다Special method names문서) 및 해당 함수의 반환 값을 사용하십시오. 요약은 다음과 같습니다.

object .__ nonzero __ (self) 진리 값 테스트 및 내장 연산을 구현하기 위해 호출됩니다. bool (); False 또는 True 또는 0 또는 1에 해당하는 정수를 반환해야합니다.이 메서드가 정의되지 않은 경우 __len __ ()이 호출되고 (정의 된 경우) 결과가 0이 아니면 객체가 true로 간주됩니다. 클래스가 __len __ () 또는 __nonzero __ ()를 정의하지 않으면 모든 인스턴스가 true로 간주됩니다.

반면에

if A is not None:

비교참조ANone동일한 지 여부를 확인합니다.


<답변2>

쓰여진대로PEP8:

None과 같은 싱글 톤에 대한 비교는 항상 'is'또는 'is not'으로 이루어져야하며, 항등 연산자가 아닙니다. 또한 실제로 "if x가 None이 아닌 경우"를 의미 할 때 "if x"를 작성하지 않도록주의하십시오. 예를 들어 기본값이 None 인 변수 나 인수가 다른 값으로 설정되었는지 테스트 할 때입니다. 다른 값은 부울 컨텍스트에서 거짓 일 수있는 유형 (예 : 컨테이너)을 가질 수 있습니다!


<답변3>

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

<답변4>

적절한 결과가 없으면 많은 함수에서 None을 반환합니다. 예를 들어 SQLAlchemy 쿼리의.first()결과에 행이 없으면 메서드는 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로 캐스팅되는 모든 값"뿐만 아니라 특정 값 (None)을 확인하고 있습니다.


<답변5>

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

아래는 A에 값 이외의 것이 있는지 확인합니다.False,[],None,''0. 그것은 확인합니다의 A.

if A:

아래는 A가 None과 다른 객체인지 확인합니다. 그것은 확인하고 비교합니다참고(메모리 주소) A 및 None.

if A is not None:

업데이트 : 추가 설명

여러 번 두 사람이 같은 일을하는 것처럼 보이므로 많은 사람들이 서로 바꿔서 사용합니다. 두 사람이 같은 결과를내는 이유는우연의 일치인터프리터 / 컴파일러의 최적화로 인해interning또는 다른 것.

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

> 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

아마도 이것은 튜플이 변경되지 않도록 보장되기 때문일 것입니다. 따라서 동일한 메모리를 재사용하는 것이 합리적입니다.

이것은 어떤 비교 연산자를 사용하는지 특별히주의해야 함을 보여줍니다. 사용하다is==당신이 정말로 확인하고 싶은 것에 따라. 이러한 것들은 디버깅하기 어려울 수 있습니다.is우리가 종종 그것을 훑어 보는 산문처럼 읽습니다.


<답변6>

내가 본 대부분의 가이드는

만약:

더 구체적인 이유가 없다면.

약간의 차이가 있습니다. False를 반환하는 None 이외의 값 (예 : 빈 목록 또는 0)이 있으므로 실제로 테스트하고있는 것이 무엇인지 생각해보십시오.


<답변7>

if A:A가 0, False, 빈 문자열, 빈 목록 또는 None이면 원하지 않는 결과가 발생할 수 있습니다.


<답변8>

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

if A is not None

거짓 값은 파이썬에서 특별한 객체 클래스입니다.(예 : 거짓, []). A가 거짓인지 테스트하려면 다음을 사용하십시오.

if not A

따라서 두 표현은 동일하지 않습니다그리고 그것들을 동의어로 취급하지 않는 것이 좋습니다.

PS None도 거짓이므로 첫 번째 표현은 두 번째 표현을 의미합니다. 그러나 두 번째는 없음 외에 다른 거짓 값을 다룹니다. 이제 ... A에서 None 외에 다른 거짓 값을 가질 수 없다고 확신 할 수 있다면 첫 번째 표현식을 두 번째 표현식으로 바꿀 수 있습니다.


<답변9>

상황에 따라 다릅니다.

나는 사용한다if A:내가 기대할 때A어떤 종류의 컬렉션이 되려면 컬렉션이 비어 있지 않은 경우에만 블록을 실행하고 싶습니다. 이를 통해 호출자는 비어 있든 없든 잘 작동하는 컬렉션을 전달하고 내가 예상 한대로 수행하도록 할 수 있습니다. 또한NoneFalse블록의 실행을 억제하기 위해 때때로 코드 호출에 편리합니다.

OTOH, 내가 기대한다면A완전히 임의의 객체이지만 기본적으로None, 그럼 내가항상사용하다if A is not None, 호출 코드가 의도적으로 빈 컬렉션, 빈 문자열 또는 0 값 숫자 형식 또는 부울에 대한 참조를 전달할 수 있기 때문입니다.False또는 부울 컨텍스트에서 거짓 인 일부 클래스 인스턴스.

다른 한편으로 내가 기대한다면A좀 더 구체적인 것 (예 : 메서드를 호출 할 클래스의 인스턴스)이지만 기본값은 다음과 같을 수 있습니다.None, 기본 부울 변환을 모든 하위 클래스에 적용해도 상관없는 클래스의 속성으로 간주하고 다음을 사용합니다.if A:추가로 12자를 입력해야하는 끔찍한 부담을 덜기 위해


<답변10>

나는라는 파일을 만들었습니다.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'>

<답변11>

다른 답변은 모두 좋은 정보를 제공했지만 명확해야한다고 생각합니다.

아니요, 다음을 사용해서는 안됩니다.

if A:

테스트해야하는 것이 다음과 같은 경우 :

if A is not None:

첫 번째는 종종 두 번째를 대체하는 역할을하지만 첫 번째는 버그를 찾기 어려운 공통 소스입니다. 당신이하고있는 모든 것이 간단한 코드 작성일지라도 버그가있는 코드를 작성하는 습관을 들이지 않도록해야합니다. 올바른 장황한 형식의 테스트를 쓰고 읽을 수 있도록 손가락과 마음을 훈련하십시오.

if A is not None: 

None의 일반적인 사용은 선택적 매개 변수 값을 정의하고 변수에 "아직 값이 없음"을 의미하는 기본 시작 값을 제공하고 "값이 반환되지 않음"을 의미합니다. 다음과 같은 함수를 작성하는 경우 :

def my_func(a_list, obj=None):
    if obj:          # Trying to test if obj was passed
        a_list.append(obj)
    # do something with a_list

이것은 다음과 같은 많은 실제 사용에서 잘 작동합니다.

my_func(user_names, "bob")

그러나 이런 일이 발생하면 :

my_func(user_names, "")
my_func(user_names, [])
my_func(user_names, 0)

그러면 길이가 0 인 개체가 목록에 추가되지 않습니다. 첫 번째 코드가 작성되었을 때 길이가 0 인 사용자 이름이 허용되지 않음을 알 수 있습니다. 따라서 짧은 코드는 잘 작동합니다. 그러나 이름이없는 익명 사용자와 같은 것을 의미하도록 빈 문자열을 사용하도록 코드를 수정하려고 시도하면 갑자기이 함수가 예상되는 작업을 중지합니다 (이름없는 사용자를 목록에 추가).

예를 들어 다음과 같이 사용자가 로그인 할 수있는시기를 정의하는 논리가 있다고 가정 해 보겠습니다.

new_user = get_user_name()

if user_list_ok(my_func(current_users, new_user)):
    # user_list_ok() tests that no more than 10 users can
    # log in at the same time, and that no sigle user can
    # can log in more than 3 times at once.

    # This user is allowed to log in!

    log_user_in(new_user)

이제 코드에 미묘하고 복잡한 버그가 생성됩니다. 익명 사용자 ""는 테스트 목록에 추가되지 않으므로 시스템이 10 명의 사용자 제한에 도달하면 테스트에서 익명 사용자가 로그인 할 수 있도록 허용하여 사용자 수를 11 개로 밀어 넣습니다. 최대 10 명의 사용자 만 필요로하는 시스템의 다른 부분에서 버그를 유발할 수 있습니다.

"var에 값이 없습니다"에 대해 테스트해야 할 때 추악하고 장황하게 느껴지더라도 항상 더 긴 "없음"테스트를 사용해야합니다.


<답변12>

전자는 더 파이썬 적이지만 (더 나은 이념적 코드) A가 False (없음이 아님)이면 블록을 실행하지 않습니다.


<답변13>

파이썬> = 2.6,

우리가 다음과 같이 쓰면

if A:

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

FutureWarning :이 메서드의 동작은 향후 버전에서 변경됩니다. 대신 특정 'len (elem)'또는 'elem is not None'테스트를 사용하십시오.

그래서 우리는

if A is not None:
728x90

댓글