[python] 함수가 여러 값을 반환하는 것이 비단뱀입니까?

파이썬에서는 함수가 여러 값을 반환하도록 할 수 있습니다. 다음은 인위적인 예입니다.

def divide(x, y):
    quotient = x/y
    remainder = x % y
    return quotient, remainder

(q, r) = divide(22, 7)

이것은 매우 유용 해 보이지만 남용 될 수도있는 것처럼 보입니다 ( “Well..function X는 이미 필요한 것을 중간 값으로 계산합니다. X도 그 값을 반환하도록합시다”).

언제 선을 그리고 다른 방법을 정의해야합니까?



답변

물론입니다 (제공 한 예의 경우).

튜플은 파이썬에서 일류 시민입니다.

divmod()정확히 그렇게 하는 내장 함수 가 있습니다.

q, r = divmod(x, y) # ((x - x%y)/y, x%y) Invariant: div*y + mod == x

다른 예는 다음과 같습니다 zip, enumerate, dict.items.

for i, e in enumerate([1, 3, 3]):
    print "index=%d, element=%s" % (i, e)

# reverse keys and values in a dictionary
d = dict((v, k) for k, v in adict.items()) # or 
d = dict(zip(adict.values(), adict.keys()))

BTW, 괄호는 대부분 필요하지 않습니다. Python Library Reference 에서 인용 :

튜플은 여러 가지 방법으로 구성 할 수 있습니다.

  • 한 쌍의 괄호를 사용하여 빈 튜플 표시 : ()
  • 싱글 톤 튜플에 후행 쉼표 사용 : a 또는 (a,)
  • 쉼표로 항목 구분 : a, b, c 또는 (a, b, c)
  • 내장 tuple () 사용 : tuple () 또는 tuple (iterable)

기능은 단일 용도로 사용되어야합니다.

따라서 단일 객체를 반환해야합니다. 귀하의 경우이 객체는 튜플입니다. 튜플을 임시 복합 데이터 구조로 간주하십시오. 거의 모든 단일 함수가 여러 값을 반환하는 언어가 있습니다 (Lisp의 목록).

때로는 (x, y)대신 반환하는 것으로 충분합니다 Point(x, y).

명명 된 튜플

Python 2.6에 명명 된 튜플이 도입되면서 많은 경우 일반 튜플 대신 명명 된 튜플을 반환하는 것이 좋습니다.

>>> import collections
>>> Point = collections.namedtuple('Point', 'x y')
>>> x, y = Point(0, 1)
>>> p = Point(x, y)
>>> x, y, p
(0, 1, Point(x=0, y=1))
>>> p.x, p.y, p[0], p[1]
(0, 1, 0, 1)
>>> for i in p:
...   print(i)
...
0
1


답변

첫째, Python은 다음을 허용합니다 (괄호가 필요 없음).

q, r = divide(22, 7)

귀하의 질문과 관련하여 어느 쪽이든 엄격하고 빠른 규칙은 없습니다. 간단한 (일반적으로 인위적인) 예제의 경우 주어진 함수가 단일 목적을 갖고 결과적으로 단일 값을 얻는 것이 항상 가능해 보일 수 있습니다. 그러나 실제 응용 프로그램에 Python을 사용할 때 여러 값을 반환해야하는 많은 경우에 빠르게 실행되어 코드가 더 깔끔해집니다.

그래서, 나는 말이되는 것은 무엇이든하고, 인위적인 관습을 따르려고하지 마십시오. Python은 여러 반환 값을 지원하므로 적절할 때 사용하십시오.


답변

당신이 제공하는 예제는 실제로라는 파이썬 내장 함수 divmod입니다. 그래서 누군가는 어느 시점에서 핵심 기능을 포함하기에 충분히 비단뱀이라고 생각했습니다.

나에게 코드를 깔끔하게 만든다면 비단뱀 적이다. 다음 두 코드 블록을 비교하십시오.

seconds = 1234
minutes, seconds = divmod(seconds, 60)
hours, minutes = divmod(minutes, 60)

seconds = 1234
minutes = seconds / 60
seconds = seconds % 60
hours = minutes / 60
minutes = minutes % 60


답변

예, 여러 값 (즉, 튜플)을 반환하는 것은 확실히 비단뱀입니다. 다른 사람들이 지적했듯이 Python 표준 라이브러리와 존경받는 Python 프로젝트에는 많은 예제가 있습니다. 두 가지 추가 설명 :

  1. 여러 값을 반환하는 것은 때때로 매우 유용합니다. 예를 들어 선택적으로 이벤트를 처리하고 (일부 값을 반환) 성공 또는 실패를 반환하는 메서드를 사용합니다. 이는 일련의 책임 패턴에서 발생할 수 있습니다. 다른 경우에는 주어진 예와 같이 밀접하게 연결된 여러 데이터 조각을 반환하려고합니다. 이 설정에서 여러 값을 반환하는 것은 여러 멤버 변수가있는 익명 클래스의 단일 인스턴스를 반환하는 것과 유사합니다.
  2. Python의 메서드 인수 처리에는 여러 값을 직접 반환하는 기능이 필요합니다. 예를 들어 C ++에서는 메서드 인수를 참조로 전달할 수 있으므로 형식적인 반환 값 외에 출력 값을 할당 할 수 있습니다. Python에서 인수는 “참조”로 전달됩니다 (그러나 C ++가 아닌 Java의 의미에서). 메서드 인수에 새 값을 할당하고 메서드 범위 외부에 반영되도록 할 수 없습니다. 예를 들면 :

    // C++
    void test(int& arg)
    {
        arg = 1;
    }
    
    int foo = 0;
    test(foo); // foo is now 1!
    

    비교 :

    # Python
    def test(arg):
        arg = 1
    
    foo = 0
    test(foo) # foo is still 0
    


답변

확실히 비단뱀입니다. 어딘가에서 반환하는 유형의 모든 조합에 대해 구조체를 정의해야하는 C와 같은 언어에서 사용할 수있는 상용구 함수에서 여러 값을 반환 할 수 있다는 사실.

그러나 단일 함수에서 10 개의 값과 같은 미친 값을 반환하는 지점에 도달하면 그 지점에서 다루기가 어려워 지므로 클래스에 번들링하는 것을 진지하게 고려해야합니다.


답변

튜플을 반환하는 것은 멋지다. 또한 파이썬 2.6에 추가 된 새로운 namedtuple에 주목하세요 :
http://docs.python.org/dev/library/collections.html#collections.namedtuple


답변

OT : RSRE의 Algol68에는 흥미로운 “/ : =”연산자가 있습니다. 예.

INT quotient:=355, remainder;
remainder := (quotient /:= 113);

몫은 3이고 나머지는 16입니다.

참고 : 일반적으로 “(x / : = y)”의 값은 몫 “x”가 참조로 할당되기 때문에 버려지지만 RSRE의 경우 반환 된 값은 나머지입니다.

cf 정수 산술-Algol68