it-swarm-vi.com

Mục đích của 'return self` từ một phương thức class?

Tôi đã bắt gặp một cái gì đó như thế này trong một dự án nguồn mở. Các phương thức sửa đổi các thuộc tính thể hiện trả về một tham chiếu đến thể hiện. Mục đích của công trình này là gì?

class Foo(object):

  def __init__(self):
    self.myattr = 0

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

Đó là cho phép xích.

Ví dụ:

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;
        },
    };
}

Bây giờ bạn có thể nói:

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

Như @Lie Ryan và @Frank Shearar đề cập, đó được gọi là "giao diện lưu loát" nhưng mô hình đó đã xuất hiện từ rất lâu.

Phần gây tranh cãi của mẫu đó là trong OO, bạn có trạng thái có thể thay đổi, do đó, một phương thức void có một loại giá trị trả về ngụ ý là this - nghĩa là, đối tượng có trạng thái cập nhật là loại giá trị trả về .

Vì vậy, trong một ngôn ngữ OO với trạng thái có thể thay đổi, hai ngôn ngữ này tương đương ít nhiều:

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

...như trái ngược với

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

Vì vậy, tôi đã nghe thấy mọi người trong quá khứ chống lại các giao diện trôi chảy vì họ thích hình thức đầu tiên. Một tên khác tôi đã nghe cho "giao diện trôi chảy" là "tàu đắm";)

Tuy nhiên, tôi nói "ít nhiều tương đương" bởi vì các giao diện trôi chảy làm tăng thêm nếp nhăn. Họ không phải "trả lại cái này". Họ có thể "trở lại mới". Đó là một cách để đạt được các đối tượng bất biến trong OO.

Vì vậy, bạn có thể có một lớp A mà (mã giả)

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

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

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

Bây giờ, mỗi phương thức trả về một đối tượng hoàn toàn mới, giữ nguyên đối tượng ban đầu. Và đó là một cách để đi vào các đối tượng bất biến mà không thực sự thay đổi nhiều trong mã của bạn.

10
Rob

Hầu hết các ngôn ngữ đều nhận thức được thành ngữ 'tự trả về' và bỏ qua nó nếu nó không được sử dụng trong một dòng. Tuy nhiên, đáng chú ý là trong Python, các hàm trả về None theo mặc định.

Khi tôi ở trường CS, người hướng dẫn của tôi đã thực hiện một rất lớn về sự khác biệt giữa các chức năng, thủ tục, thói quen và phương thức; nhiều câu hỏi tiểu luận nhồi nhét bằng tay đã được đưa ra với bút chì cơ học đang nóng trong tay tôi về tất cả những điều đó.

Có thể nói, tự trả về là cách dứt khoát OO để tạo các phương thức lớp, nhưng Python cho phép nhiều giá trị trả về, bộ dữ liệu, danh sách, đối tượng, nguyên hàm hoặc Không có.

Chuỗi, như họ đã nói, chỉ đơn thuần là đưa câu trả lời cho thao tác cuối cùng vào hoạt động tiếp theo và thời gian chạy của Python có thể tối ưu hóa loại điều đó. Hiểu danh sách là một dạng tích hợp của này. (Rất mạnh mẽ!)

Vì vậy, trong Python, điều quan trọng là mọi phương thức hoặc hàm đều trả về mọi thứ, đó là lý do tại sao mặc định là Không có.

Có một trường phái cho rằng mọi hành động trong một chương trình nên báo cáo thành công, thất bại hoặc dẫn đến bối cảnh hoặc đối tượng được viện dẫn của nó, nhưng sau đó không nói về Yêu cầu của DOD ADA ở đây. Nếu bạn cần nhận phản hồi từ một phương pháp, hãy tiếp tục hoặc không, nhưng cố gắng nhất quán về nó.

Nếu một phương thức có thể thất bại, nó sẽ trả về thành công hoặc thất bại hoặc đưa ra một ngoại lệ cần xử lý.

Một lưu ý là nếu bạn sử dụng thành ngữ tự trả về, Python sẽ cho phép bạn gán tất cả các phương thức của mình cho các biến và bạn có thể nghĩ rằng bạn đang nhận được kết quả dữ liệu hoặc danh sách khi bạn thực sự nhận được đối tượng.

Các ngôn ngữ hạn chế kiểu hét lên và la hét và phá vỡ khi bạn cố gắng làm điều này, nhưng những ngôn ngữ được giải thích (Python, Lua, LISP) năng động hơn nhiều.

8
Chris Reid

Trong Smalltalk, mọi phương thức không trả lại một cách rõ ràng một cái gì đó, đều có một "tự trả về" ngầm.

Đó là bởi vì (a) có mọi phương thức trả về một cái gì đó làm cho mô hình điện toán trở nên đồng nhất hơn và (b) nó rất hữu ích khi các phương thức tự trả về. Josh K đưa ra một ví dụ hay.

4
Frank Shearar

Ưu điểm của việc trả lại một đối tượng (return self)

  • Thí dụ:

    print(foo.modify1().modify2())
    
    # instaed of
    foo.modify1()
    foo.modify2()
    print(foo)
    
  • Phong cách phổ biến hơn trong cộng đồng lập trình (tôi nghĩ).

Ưu điểm của việc biến đổi một đối tượng (không return self)

  • Khả năng sử dụng return cho các mục đích khác.
  • Guido van Rossum chấp thuận kiểu này (Tôi không đồng ý với lập luận của anh ấy).
  • Phong cách phổ biến hơn trong cộng đồng Python (tôi nghĩ).
  • Mặc định (mã nguồn ít hơn).
2
xged