수업 방법에서 '자기 귀환'의 목적은 무엇입니까?


46

오픈 소스 프로젝트에서 이와 같은 것을 발견했습니다. 인스턴스 속성을 수정하는 메소드는 인스턴스에 대한 참조를 리턴합니다. 이 구성의 목적은 무엇입니까?

class Foo(object):

  def __init__(self):
    self.myattr = 0

  def bar(self):
    self.myattr += 1
    return self

2
그리고 이것은 거의 모든 jQuery가 작성되는 방식입니다. 거의 모든 함수가 jQuery 객체를 반환합니다
CaffGeek

11
왜 그렇게 작성된 코드를 믿지 않습니까?
sepp2k

답변:


65

연결을 허용해야합니다.

예를 들면 다음과 같습니다.

var Car = function () {
    return {
        gas : 0,
        miles : 0,
        drive : function (d) {
            this.miles += d;
            this.gas -= d;
            return this;
        },
        fill : function (g) {
            this.gas += g;
            return this;
        },
    };
}

이제 당신은 말할 수 있습니다 :

var c = Car();
c.fill(100).drive(50);
c.miles => 50;
c.gas => 50;

20
기록을 위해, 이런 종류의 체인은 일반적으로 유창한 인터페이스가있는 코드에서 볼 수 있습니다 .
Lie Ryan

10

@Lie Ryan과 @Frank Shearar가 언급했듯이,이를 "유창한 인터페이스"라고 부르지 만 그 패턴은 정말 오랫동안 존재 해 왔습니다.

그 패턴의 논란의 여지가있는 부분은 OO에서 변경 가능한 상태이므로 void 메소드에는 일종의 묵시적 반환 값이 있습니다 this. 즉, 업데이트 된 상태의 객체는 일종의 반환 값입니다.

따라서 변경 가능한 상태의 OO 언어에서이 두 가지는 거의 동일합니다.

a.doA()
a.doB()
a.doC()

...와 반대로

a.doA().doB().doC()

그래서 나는 과거의 사람들이 첫 번째 형태를 좋아하기 때문에 유창한 인터페이스에 저항한다고 들었습니다. "유창한 인터페이스"라고 들었던 다른 이름은 "train wreck"입니다.;)

나는 유창한 인터페이스가 주름을 더하기 때문에 "거의 동등하다"라고 말합니다. 그들은 이것을 "반환"할 필요가 없습니다. 그들은 "새로 돌아올 수있다". 그것은 OO에서 불변의 객체를 얻는 방법입니다.

그래서 당신은 클래스 A를 가질 수 있습니다 (의사 코드)

function doA():
    return new A(value + 1)

function doB():
    return new A(value * 2)

function doC():
    return new A(sqrt(value))

이제 각 메소드는 새로운 객체를 반환하고 초기 객체는 변경하지 않습니다. 그리고 이것은 코드에서 크게 변경하지 않고 불변의 객체로 들어가는 방법입니다.


그래도 메소드가을 반환 new(...)하면 메모리가 누출됩니다.
smci

@smci 언어, 구현 및 사용법에 크게 의존합니다. 물론 C ++ 인 경우 모든 곳에서 메모리가 누출 될 수 있습니다. 그러나 이것은 가비지 컬렉터가있는 언어로 간단하게 정리됩니다. GC의 유무에 관계없이 일부 구현은 새 객체 중 하나가 사용되지 않을 때를 감지하고 실제로 아무것도 할당하지 않을 수도 있습니다.
비트 트리

@ 8bittree : 우리는 파이썬에 대해 이야기하고 있습니다.이 질문은 8 년 전에 Python으로 태그되었습니다. 파이썬 GC는 처음에는 메모리가 누출되지 않는 것이 좋지 않습니다. __init__반복해서 호출하면 오버 헤드가 발생합니다.
smci

8

대부분의 언어는 '반환 자아'관용구를 알고 있으며, 줄에서 사용되지 않으면 무시합니다. 그러나 파이썬에서는 함수 None가 기본적으로 반환된다는 점이 주목할 만합니다 .

내가 CS 학교에있을 때 내 강사가 만든 거대한 함수, 프로 시저, 루틴 및 방법의 차이에 대한 거래를; 손에 닿는 에세이 문제는 기계 연필이 내 손에 뜨거워지면서 시작되었습니다.

말할 것도없이 self를 리턴하는 것은 클래스 메소드를 작성하는 결정적인 OO 방법이지만 Python은 다중 리턴 값, 튜플,리스트, 객체, 프리미티브 또는 없음을 허용합니다.

체인화는 마지막 작업에 대한 대답을 다음 작업에 넣는 것 뿐이며 Python 런타임은 이러한 종류의 것을 최적화 할 수 있습니다. 리스트 이해는 이것에 내장 된 형태입니다. (아주 세다!)

따라서 파이썬에서는 모든 메소드 또는 함수가 물건을 반환하는 것이 중요하지 않으므로 기본값은 없음입니다.

프로그램의 모든 행동이 성공, 실패 또는 결과를 호출하는 맥락이나 대상에 다시보고해야하지만 여기에서 국방부 ADA 요구 사항에 대해 이야기하지 않았다고 생각하는 학교가 있습니다. 메소드에서 피드백을 받아야하는 경우 계속 진행하되 일관성을 유지하십시오.

메소드가 실패 할 경우 성공 또는 실패를 리턴하거나 처리 할 예외를 발생시켜야합니다.

한 가지주의 할 점은 리턴 자체 관용구를 사용하면 Python에서 모든 메소드를 변수에 할당 할 수 있으며 실제로 객체를 가져올 때 데이터 결과 또는 목록을 얻는다고 생각할 수 있습니다.

형식 제한 언어는이 작업을 시도 할 때 비명을 지르며 소리를 지르고 끊어 지지만 해석되는 언어 (Python, Lua, Lisp)는 훨씬 더 역동적입니다.


4

스몰 토크에서 명시 적으로 무언가를 반환하지 않는 모든 메소드에는 암시적인 "반환 자체"가 있습니다.

왜냐하면 (a) 모든 메소드가 무언가를 리턴하도록하는 것은 컴퓨팅 모델을보다 균일하게 만들고 (b) 메소드가 자체를 리턴하게하는 것이 매우 유용하기 때문입니다. 조쉬 K는 좋은 예입니다.


흥미있는 ... in Python, 명시 적으로 무언가를 반환하지 않는 모든 메소드에는 암시적인 "return None"이 있습니다.
Job

2

객체 반환의 장점 ( return self)

  • 예:

    print(foo.modify1().modify2())
    
    # instaed of
    foo.modify1()
    foo.modify2()
    print(foo)
    
  • 프로그래밍 커뮤니티에서 더 인기있는 스타일 (제 생각에).

객체를 돌연변이시키는 장점 (no return self)

  • return다른 목적으로 사용 하는 능력 .
  • 귀도 반 로섬 (Guido van Rossum )은이 스타일을 승인합니다 (저는 그의 주장에 동의하지 않습니다).
  • 파이썬 커뮤니티에서 더 인기있는 스타일 (제 생각에).
  • 기본값 (소스 코드가 적음).

귀도 논쟁은 나에게 매력적입니다. 특히 "독자가 각 방법에 대해 잘 알고 있어야합니다"에 대해 이야기하는 부분입니다. 체인
Nath

@Nat 문자열 처리 작업이 나머지 작업과 근본적으로 어떻게 다른가요?
xged

차이점은 문자열 케이스가 매번 완전히 다른 객체를 생성한다는 것입니다. 즉, 항목을 수정하지 않았습니다. 기존 개체가 수정되지 않는 것이 분명합니다. 귀환 자체가 암묵적인 언어에서는 그 반대가 사실이지만 혼합 환경은 문제가있는 것 같습니다
Nath

@ Mat 방금 파이썬 문자열이 변경 불가능하다는 것을 기억했습니다. 그것은 내 질문에 완전히 대답합니다.
xged

1
@Matt "기존 객체가 수정되고 있지 않다는 것이 확실합니다"– 단지보기 만해도 명확하지 않습니다.
xged
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.