반품, 반품 없음, 전혀 반품이 없습니까?


386

세 가지 기능을 고려하십시오.

def my_func1():
  print "Hello World"
  return None

def my_func2():
  print "Hello World"
  return

def my_func3():
  print "Hello World"

그들은 모두 None을 반환하는 것으로 보입니다. 이 함수의 반환 값이 동작하는 방식에 차이가 있습니까? 하나를 선호하는 이유가 있습니까?


40
스타일 차이가 있습니다. return None함수에 때로는 None반환 값 이 아닌 값이 있지만의 위치 return None에는 그러한 반환 값이 없음을 나타냅니다. 전혀 '아니오'라고 쓰면 return"함수"가 아니라 "절차"와 같은 흥미로운 반환 값이 없다는 것을 의미합니다. return이전 시점에 따라 "절차"에서 일찍 존재 함을 의미합니다.

답변:


500

실제 행동에는 차이가 없습니다. 그들은 모두 돌아 None오고 그게 다야. 그러나이 모든 것들을위한 시간과 장소가 있습니다. 다음 지침은 기본적으로 다른 방법을 사용해야하는 방법 (또는 적어도 내가 가르쳐야하는 방법)이지만 절대적인 규칙은 아니므로 필요한 경우 혼합 할 수 있습니다.

사용 return None

이것은 함수가 실제로 나중에 사용하기 위해 값을 반환한다는 의미이며,이 경우에는를 반환합니다 None. None그런 다음 이 값 을 다른 곳에서 사용할 수 있습니다. return None함수에서 다른 가능한 반환 값이 없으면 사용되지 않습니다.

다음 예제에서, 우리는 반환이 personmother경우 생성 person주어진 인간이다. 그것이 인간이 아니라면, 우리 는 동물 이 아니기 None때문에 돌아온다 (동물이나 동물이 아니라고 가정하자).personmother

def get_mother(person):
    if is_human(person):
        return person.mother
    else:
        return None

사용 return

이것은 break루프에서 와 같은 이유로 사용됩니다 . 반환 값은 중요하지 않으며 전체 기능을 종료하려고합니다. 자주 필요하지 않더라도 일부 장소에서 매우 유용합니다.

우리는 15를 prisoners가지고 있고 그들 중 하나가 칼을 가지고 있음을 알고 있습니다. prisoner칼이 있는지 확인하기 위해 하나씩 하나씩 반복합니다 . 우리가 칼로 사람을 때리면 칼이 하나만 있고 나머지는 검사 할 이유가 없기 때문에 함수를 종료 할 수 있습니다 prisoners. 칼로을 찾지 못하면 prisoner경고를 발생시킵니다. 이것은 여러 가지 방법으로 수행 될 수 있으며 사용하는 return것이 가장 좋은 방법은 아니지만 return기능 종료 에 사용하는 방법을 보여주는 예제 일뿐 입니다.

def find_prisoner_with_knife(prisoners):
    for prisoner in prisoners:
        if "knife" in prisoner.items:
            prisoner.move_to_inquisition()
            return # no need to check rest of the prisoners nor raise an alert
    raise_alert()

참고 : var = find_prisoner_with_knife()반환 값이 잡히지 않기 때문에 절대로하지 말아야합니다 .

더 사용하지 return전혀

이 또한 반환 None하지만 해당 값은 사용되거나 포착되지 않습니다. 그것은 단순히 기능이 성공적으로 종료되었음을 의미합니다. 그것은 기본적으로 동일합니다 return에서 void같은 C ++ 또는 Java와 같은 언어 기능.

다음 예에서는 사람의 어머니 이름을 설정 한 다음 성공적으로 완료된 후 기능이 종료됩니다.

def set_mother(person, mother):
    if is_human(person):
        person.mother = mother

참고 : var = set_mother(my_person, my_mother)반환 값이 잡히지 않기 때문에 절대로하지 말아야합니다 .


5
var = get_mother()당신이 var받아 들일 수있는 다른 함수로 넘어 가면 괜찮습니다 None– "never"는 조금 극단적입니다
joelb

var = get_mother()사용할 수없는 경우 반환 값을 어떻게 받아 들여야 합니까? IMHO 그렇게해도 괜찮습니다. 사용하기 전에 None값이 아닌지 확인해야 if var합니다.
winklerrr

나는 이것이 좋은 컨벤션이 아니라 PEP8에 요구된다고 언급하는 것이 중요하다고 생각했다. 나는 당신을 칭찬하는 답변을 게시하고 이것에 PEP8을 인용합니다.
Fabiano

29

예, 모두 동일합니다.

해석 된 기계어 코드를 검토하여 모두 동일한 작업을 수행하고 있음을 확인할 수 있습니다.

import dis

def f1():
  print "Hello World"
  return None

def f2():
  print "Hello World"
  return

def f3():
  print "Hello World"

dis.dis(f1)
    4   0 LOAD_CONST    1 ('Hello World')
        3 PRINT_ITEM
        4 PRINT_NEWLINE

    5   5 LOAD_CONST    0 (None)
        8 RETURN_VALUE

dis.dis(f2)
    9   0 LOAD_CONST    1 ('Hello World')
        3 PRINT_ITEM
        4 PRINT_NEWLINE

    10  5 LOAD_CONST    0 (None)
        8 RETURN_VALUE

dis.dis(f3)
    14  0 LOAD_CONST    1 ('Hello World')
        3 PRINT_ITEM
        4 PRINT_NEWLINE            
        5 LOAD_CONST    0 (None)
        8 RETURN_VALUE      

4
조심 여기에 dis.dis반환 None: -X
mgilson

dis를 문자열로 출력하는 유일한 방법은 stdout을 일종의 IO 버퍼 (예 : StringIO)로 리디렉션하는 것입니다. 그럼에도 불구하고, 직접 비교해 dis.dis도 효과가 없을 수도 있습니다. 일부 라인 번호도보고합니다.
mgilson

어쨌든 정확히 동일한 레지스터를 사용하고 있는지 여부와는 관련이 없으므로 코드를 변경하여 일종의 구피 문자열 비교 대신 기계 코드를 눈에 띄게 보았습니다. 매우 큰 감사합니다.
David Marx

19

각각 동일한 싱글 톤을 반환합니다 None. 기능상의 차이는 없습니다.

나는 return함수를 일찍 (이 경우 베어 return가 더 흔하게) 빠져 나가 거나 그렇지 않은 다른 것을 반환 하지 않으면 명령문 을 떠나는 것이 관용적이라고 생각합니다 None. 또한 return None다른 것이 아닌 다른 경로를 갖는 함수에있을 때 쓰는 것이 의미가 있고 관용적 인 것처럼 보입니다 None. return None명시 적으로 작성 하는 것은 독자에게 더 흥미로운 무언가를 반환하는 또 다른 분기가 있다는 시각적 신호입니다 (호출 코드는 두 유형의 반환 값을 모두 처리해야 할 것입니다).

종종 파이썬에서 반환 None하는 void함수는 C의 함수 와 같이 사용됩니다 .-전역 데이터를 사용하지 않는 한 ( shudders ) 않는 한 일반적으로 입력 인수 를 처리하는 것 입니다. 일반적으로 반환 하면 인수가 변경되었다는 것이 더 명확 해집니다. 이것은 "언어 규약"관점에서 진술 을 철회하는 것이 왜 합리적인지 조금 더 분명하게 만듭니다 .Nonereturn

즉, 이미 미리 설정된 규칙이있는 코드베이스에서 작업하는 경우 코드베이스가 균일하게 유지되도록 돕기 위해 분명히 따라야합니다 ...


1
또는 더 일반적으로, return명령문을 누르지 않고 함수가 종료되면를 반환합니다 None.

함수가 값을 반환 할 것으로 예상되는 경우 return 문을 생략하는 것은 관용적이지 않습니다. 부작용을 통해서만 작동하는 함수 만 return 문을 생략해야합니다.
분자

@ molecule-네, 아마도 제가 여기서 설명 할 때 최선을 다하지 않았다고 생각합니다. 위의 (훨씬 더 나은) 답변의 완전한 복제본으로 만들지 않고 업데이트하려고했습니다. 나는 여전히이 게시물에 대해 행복하지 않습니다 ... 내 부분은 그것을 삭제하고 싶습니다 (위의 답변이 훨씬 낫기 때문에). 내 일부는 그것을 유지하고 싶어합니다. 지금까지 9 명이 좋았다고 생각했습니다. 한 가지 이유. 다른 사람이 놓친 것을 칠 수도 있을까요?
mgilson 2016 년

1
@ZAB-나는 그것이 가능하지 않다고 생각합니다. 파이썬에서는 무엇이든 무엇이든 원숭이 패치 할 수 있습니다 (이것은 의도적으로 설계된 것이므로 드물게 사용하면 큰 기능입니다). 특히, 나는 반환하지 않는 함수를 원숭이 패치 할 수 있습니다. 모든 "표현식 아님"검사는 구문 분석 시간에 발생하지만 원숭이 패치로 인해 런타임까지 발생할 수 없습니다. IOW, 완전히 다릅니다. 개인적으로, 나는 현재의 행동이 상당히 합리적이며 다른 고급 언어와 일관성이 있다고 생각하지만, 당신이 설득해야 할 것은 아닙니다 :-).
mgilson

1
@ZAB은 - 모두 RubyJavascript파이썬과 같은 접근 방식을. 나는 표현에 "void"라고 말하는 고급 언어의 예가 있다고 확신하지만 현재 생각할 수 없습니다 ( Java고급 언어 를 고려한다면 ) ... 원숭이 패치 함수 (다른 것들 중에서 테스트에서 조롱하는 데 유용함)는 파이썬이 void키워드를 가져 와서 함수가 아무것도 반환하지 않는 가상의 세계에서 작동 합니까? (또한 이전에 말했듯이이 디자인이 잘못된 디자인이라는 것을 확신 할 필요는 없습니다. 옳은 경우에도 아무 것도 할 수 없습니다)
mgilson

4

다른 사람들이 대답했듯이 결과는 정확히 동일 None하며 모든 경우에 반환됩니다.

차이점은 문체이지만 PEP8 에서는 일관성있게 사용해야합니다.

반환 진술에서 일관성을 유지하십시오. 함수의 모든 return 문은 표현식을 반환하거나 그 중 어느 것도 반환하지 않아야합니다. 리턴 문이 표현식을 리턴하는 경우, 값이 리턴되지 않은 리턴 문은이를 명시 적으로 리턴 없음으로 표시해야하며 함수 끝에 도달 할 수있는 경우 명시 적 리턴 문이 있어야합니다.

예:

def foo(x):
    if x >= 0:
        return math.sqrt(x)
    else:
        return None

def bar(x):
    if x < 0:
        return None
    return math.sqrt(x)

아니:

def foo(x):
    if x >= 0:
        return math.sqrt(x)

def bar(x):
    if x < 0:
        return
    return math.sqrt(x)

https://www.python.org/dev/peps/pep-0008/#programming-recommendations


기본적으로 None함수에서 비값을 반환 하면 반환 값에 의미가 있으며 호출자가 잡을 수 있습니다. 따라서을 반환 할 때 None명시 적으로 표현해야합니다 None.이 경우 전달할 수 있는 의미는 반환 값 중 하나입니다.

전혀 리턴이 필요하지 않으면 함수는 기본적으로 함수 대신 프로 시저로 작동하므로 return명령문을 포함하지 마십시오 .

프로 시저와 같은 함수를 작성 중이고 더 일찍 리턴 할 기회가있는 경우 (즉, 해당 시점에서 이미 완료되었으며 나머지 함수를 실행할 필요가없는 경우) 빈 returns를 사용 하여 독자에게 신호를 보낼 수 있습니다. 그것은 실행의 초기 마무리 일 뿐이며 None암시 적으로 반환 된 값은 의미가 없으며 잡히지 않아야합니다 (절차와 같은 함수는 항상 None어쨌든 반환 합니다).


3

기능면에서 이들은 모두 동일하며, 차이점은 코드 가독성과 스타일에 있습니다 (고려해야 함).

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