[python] 함수에서 여러 값을 어떻게 반환합니까? [닫은]

이를 지원하는 언어로 여러 값을 반환하는 표준 방법은 종종 튜플 링 입니다.

옵션 : 튜플 사용

이 사소한 예를 고려하십시오.

def f(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return (y0, y1, y2)

그러나 반환되는 값의 수가 증가함에 따라 이는 빠르게 문제가됩니다. 4 개 또는 5 개의 값을 반환하려면 어떻게합니까? 물론, 계속 튜플 링 할 수는 있지만 어느 값이 어디에 있는지 잊어 버릴 수 있습니다. 또한 원하는 곳 어디에서나 포장을 풀면 추악합니다.

옵션 : 사전 사용

다음 논리적 단계는 일종의 ‘레코드 표기법’을 도입하는 것 같습니다. 파이썬에서이를 수행하는 확실한 방법은을 사용하는 것입니다 dict.

다음을 고려하세요:

def g(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return {'y0': y0, 'y1': y1 ,'y2': y2}

명확하게 말하면, y0, y1 및 y2는 추상적 식별자로 의미됩니다. 실제로 지적한 바와 같이 의미있는 식별자를 사용합니다.

이제 반환 된 객체의 특정 멤버를 투영 할 수있는 메커니즘이 있습니다. 예를 들어

result['y0']

옵션 : 수업 사용

그러나 다른 옵션이 있습니다. 대신 특수 구조를 반환 할 수 있습니다. 파이썬의 맥락 에서이 프레임을 만들었지 만 다른 언어에도 적용된다고 확신합니다. 실제로 C에서 작업하는 경우 이것이 유일한 옵션 일 수 있습니다. 간다 :

class ReturnValue:
  def __init__(self, y0, y1, y2):
     self.y0 = y0
     self.y1 = y1
     self.y2 = y2

def g(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return ReturnValue(y0, y1, y2)

파이썬에서 앞의 두 아마도 배관의 측면에서 매우 유사하다 – 결국 { y0, y1, y2 }단지 내부의 항목 끝나게 __dict__ReturnValue.

작은 객체, __slots__속성에 대해 Python이 제공하는 추가 기능이 하나 있습니다 . 수업은 다음과 같이 표현 될 수 있습니다.

class ReturnValue(object):
  __slots__ = ["y0", "y1", "y2"]
  def __init__(self, y0, y1, y2):
     self.y0 = y0
     self.y1 = y1
     self.y2 = y2

로부터 파이썬 참조 설명서 :

__slots__선언 각 변수에 대한 값을 유지하도록 각각의 인스턴스 인스턴스 변수 보유 충분한 공간의 시퀀스 걸린다. __dict__각 인스턴스마다 공간이 생성되지 않아 공간이 절약 됩니다.

옵션 : 데이터 클래스 사용 (Python 3.7 이상)

Python 3.7의 새로운 데이터 클래스를 사용하여 자동으로 추가 된 특수 메소드, 입력 및 기타 유용한 도구가있는 클래스를 리턴하십시오.

@dataclass
class Returnvalue:
    y0: int
    y1: float
    y3: int

def total_cost(x):
    y0 = x + 1
    y1 = x * 3
    y2 = y0 ** y3
    return ReturnValue(y0, y1, y2)

옵션 : 목록 사용

내가 간과 한 또 다른 제안은 Bill the Lizard에서 온 것입니다.

def h(x):
  result = [x + 1]
  result.append(x * 3)
  result.append(y0 ** y3)
  return result

이것은 내가 가장 좋아하는 방법입니다. 나는 Haskell에 노출되어 오염되었다고 생각하지만 혼합 유형 목록의 아이디어는 항상 나에게 불편하다고 느꼈습니다. 이 특정 예제에서 목록은 혼합 유형이 아니지만 가능할 수 있습니다.

이 방법으로 사용 된 목록은 실제로 내가 알 수있는 한 튜플과 관련하여 아무것도 얻지 못합니다. 파이썬에서 목록과 튜플의 유일한 차이점은 목록은 변경 가능 하지만 튜플은 변경 불가능 하다는 것 입니다.

필자는 개인적으로 함수형 프로그래밍에서 관례를 따르는 경향이 있습니다. 동일한 유형의 여러 요소에 대해 목록을 사용하고 미리 결정된 유형의 고정 된 요소에 대해 튜플을 사용하십시오.

질문

긴 서문 후에 피할 수없는 질문이 온다. 가장 좋은 방법은 무엇입니까?



답변

이 목적으로 명명 된 튜플 이 2.6에 추가되었습니다. 유사한 내장 예제는 os.stat 를 참조하십시오 .

>>> import collections
>>> Point = collections.namedtuple('Point', ['x', 'y'])
>>> p = Point(1, y=2)
>>> p.x, p.y
1 2
>>> p[0], p[1]
1 2

최신 버전의 Python 3 (3.6 이상, 내 생각에)에서 새로운 typing라이브러리는 NamedTuple명명 된 튜플을 더 쉽고 강력하게 만들 수 있는 클래스를 얻었습니다 . 상속은 문서 typing.NamedTuple문자열, 기본값 및 형식 주석을 사용할 수있게합니다.

예 (문서에서) :

class Employee(NamedTuple):  # inherit from typing.NamedTuple
    name: str
    id: int = 3  # default value

employee = Employee('Guido')
assert employee.id == 3


답변

작은 프로젝트의 경우 튜플을 사용하는 것이 가장 쉽다는 것을 알았습니다. 그것이 관리하기가 너무 어려워지면 (이전이 아닌) 논리 구조로 그룹화하기 시작하지만 제안 된 사전과 ReturnValue객체의 사용이 잘못되었거나 너무 단순 하다고 생각합니다 .

키 사전을 반환 "y0", "y1", "y2", 등 튜플을 통해 어떤 이점을 제공하지 않습니다. 돌아 오는 ReturnValue특성을 가진 인스턴스를 .y0, .y1, .y2, 등 중 튜플을 통해 어떤 이점을 제공하지 않습니다. 어디든 가려면 이름을 지정해야합니다. 어쨌든 튜플을 사용하여 이름을 지정할 수 있습니다.

def get_image_data(filename):
    [snip]
    return size, (format, version, compression), (width,height)

size, type, dimensions = get_image_data(x)

IMHO, 튜플을 넘어서는 유일한 좋은 기술은 re.match()또는 에서 얻는 것처럼 적절한 방법과 속성을 사용하여 실제 객체를 반환하는 것 open(file)입니다.


답변

많은 답변은 사전이나 목록과 같은 일종의 컬렉션을 반환해야한다고 제안합니다. 추가 구문을 생략하고 쉼표로 구분하여 반환 값을 쓸 수 있습니다. 참고 : 이것은 기술적으로 튜플을 반환합니다.

def f():
    return True, False
x, y = f()
print(x)
print(y)

제공합니다 :

True
False


답변

사전에 투표합니다.

2-3 개 이상의 변수를 반환하는 함수를 만들면 사전에 접을 것입니다. 그렇지 않으면 나는 돌아 오는 것의 순서와 내용을 잊어 버리는 경향이있다.

또한 ‘특별한’구조를 도입하면 코드를 따르기가 더 어려워집니다. (다른 사람은 코드를 검색하여 코드를 찾아야합니다.)

유형 조회에 관심이있는 경우 설명 사전 키 (예 : ‘x- 값 목록’)를 사용하십시오.

def g(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return {'y0':y0, 'y1':y1 ,'y2':y2 }


답변

다른 옵션은 생성기를 사용하는 것입니다.

>>> def f(x):
        y0 = x + 1
        yield y0
        yield x * 3
        yield y0 ** 4


>>> a, b, c = f(5)
>>> a
6
>>> b
15
>>> c
1296

IMHO 튜플이 일반적으로 가장 좋지만 반환되는 값이 클래스의 캡슐화 후보 인 경우를 제외하고는 가장 좋습니다.


답변

튜플이 “자연 스럽다”고 느낄 때마다 튜플을 사용하는 것을 선호합니다. 좌표는 일반적인 예이며, 예를 들어 1 축만 스케일링 계산에서 별도의 객체가 자체적으로 존재할 수 있으며 순서가 중요합니다. 참고 : 그룹의 의미에 부정적인 영향을 미치지 않고 항목을 정렬하거나 섞을 수 있다면 튜플을 사용하지 않아야합니다.

그룹화 된 객체가 항상 같지 않은 경우에만 사전을 반환 값으로 사용합니다. 선택적인 이메일 헤더를 생각하십시오.

그룹화 된 객체가 그룹 내부에 고유 한 의미를 가지고 있거나 자체 메서드가있는 본격적인 객체가 필요한 나머지 경우에는 클래스를 사용합니다.


답변

나는 선호한다:

def g(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return {'y0':y0, 'y1':y1 ,'y2':y2 }

다른 모든 것은 동일한 일을하기위한 추가 코드 일뿐입니다.