Bir sınıf yönteminden “dönüş öz” amacı?


46

Açık kaynaklı bir projede bunun gibi bir şeyle karşılaştım. Örnek niteliklerini değiştiren yöntemler, örneğe bir referans döndürür. Bu yapının amacı nedir?

class Foo(object):

  def __init__(self):
    self.myattr = 0

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

2
Ve bu, jQuery'nin hemen hemen bütünüyle yazıldığı şeydir. Neredeyse her fonksiyon bir jQuery nesnesi döndürür
CaffGeek

11
Neden böyle yazılmış bir koda güvenmiyorsun?
sepp2k

Yanıtlar:


65

Zincirlemeye izin vermek.

Örneğin:

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

Şimdi söyleyebilirsiniz:

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

20
Kayıt için, bu tür bir zincirleme genellikle akıcı arayüzlü kodda görülür .
Lie Ryan

10

@Lie Ryan ve @Frank Shearar'ın belirttiği gibi, buna "akıcı arayüz" denir, ancak bu model çok uzun zamandır etraftadır.

Bu modelin tartışmalı kısmı OO'da değişken duruma sahip olmanızdır, bu nedenle bir geçersiz yöntem, bir tür ima edilen iade değerine sahiptir this- yani, güncellenmiş durumdaki nesne, geri dönüş değerinin türüdür.

Yani değişken durumdaki bir OO dilinde, bu ikisi az ya da çok eşdeğerdir:

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

...aksine

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

Bu yüzden geçmişte insanların akıcı arayüzlere dirençli olduklarını duydum çünkü ilk şekli sevdiler. "Akıcı arayüz" için duyduğum başka bir isim "tren kazası";)

Akıcı arayüzler bir kırışıklık eklediği için "az ya da çok eşdeğer" diyorum. "Bunu geri vermek" zorunda değiller. "Yeni dönebilirler". OO'da değişmez nesnelere ulaşmanın bir yolu.

Böylece A sınıfı olabilir (sözde kodu).

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

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

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

Şimdi, her yöntem yeni bir nesneyi döndürerek ilk nesneyi değiştirmeden bıraktı. Ve bu, kodunuzda çok fazla değişiklik yapmadan, değişmez nesnelere girmenin bir yoludur.


Tamam, ama yöntemlerin geri dönerse new(...), bu bellek sızdırıyor.
smci

@smci Bu, büyük ölçüde dile, uygulamaya ve kullanıma bağlı olacaktır. Elbette, eğer C ++ ise, muhtemelen her yere bellek sızdırıyor olacaksınız. Ancak bu, çöp toplayıcılı bir dil tarafından önemsiz şekilde temizlenir. Bazı uygulamalar (GC'li veya GC'siz), bu yeni nesnelerden birinin kullanılmadığını ve gerçekte hiçbir şey tahsis etmediğini bile tespit edebilir.
8bittree

@ 8bittree: Python hakkında konuşuyoruz, bu soru 8 yıl önce Python olarak etiketlendi. Python GC, ilk etapta hafıza sızdırmamak için en iyisi değildir. Aramak __init__tekrar tekrar ek yükü de beraberinde getirir.
smci

8

Çoğu dil, 'kendi kendine dönüş' deyiminin farkındadır ve bir satırda kullanılmıyorsa onu yoksay. Bununla birlikte, Python'da işlevlerin Nonevarsayılan olarak döndürülmesi dikkat çekicidir .

CS okulundayken, hocam işlevler, prosedürler, rutinler ve yöntemler arasındaki farklar konusunda çok şey yaptı; birçok el sıkışma denemesi sorusu, bu konuda ellerimde ısınan mekanik kurşun kalemlerle ortaya çıktı.

Kendini geri getirmenin, sınıf yöntemlerini oluşturmanın kesin OO yöntemi olduğunu söylemek yeterlidir, ancak Python çoklu dönüş değerlerine, perdelere, listelere, nesnelere, ilkellere veya Yok'a izin verir.

Zincirleme, koydukları gibi, sadece son işleme verilen cevabı bir sonrakine koyuyor ve Python çalışma zamanı bu tür şeyleri optimize edebiliyor. Liste kavramaları bunun yerleşik bir şeklidir. (Çok güçlü!)

Dolayısıyla Python'da her yöntemin veya fonksiyonun bir şeyler döndürmesi o kadar önemli değildir, bu nedenle varsayılan Yoktur.

Bir programdaki her eylemin başarısını, başarısızlığını veya sonucunu çağrıcı bağlamına veya nesnesine geri bildirmesi gerektiği, ancak daha sonra burada DOD ADA Gereklilikleri hakkında konuşmadığı bir düşünce okulu var. Bir yöntemden geri bildirim almanız gerekirse, devam edin veya devam edin, ancak bu konuda tutarlı olmaya çalışın.

Bir yöntem başarısız olursa, başarı veya başarısızlık döndürmeli veya ele alınması gereken bir istisna oluşturmalıdır.

Bir uyarı, kendi kendine dönüş deyimini kullanırsanız, Python'un tüm yöntemlerinizi değişkenlere atamanıza izin vereceği ve aslında nesneyi aldığınızda bir veri sonucu veya liste aldığınızı düşünebilirsiniz.

Tip kısıtlayıcı diller, bunu yapmaya çalıştığınızda çığlık atıyor ve bağırıyorlar, ancak yorumlananlar (Python, Lua, Lisp) çok daha dinamik.


4

Smalltalk'ta, açıkça bir şey döndürmeyen her yöntem, örtük bir "geri dönüş özeti" na sahiptir.

Bunun nedeni, (a) her yöntemin bir şeyi döndürmesini sağlamak, bilgisayar modelini daha düzgün hale getirmesi ve (b) yöntemlerin kendiliğinden dönmesi çok yararlıdır. Josh K güzel bir örnek veriyor.


İlginçtir ki ... Pythonaçıkça, bir şeyi açıkça geri getirmeyen her yöntem, örtük bir "geri dönüş Yok" a sahiptir.
İş

2

Bir nesneyi döndürmenin artıları ( return self)

  • Örnek:

    print(foo.modify1().modify2())
    
    # instaed of
    foo.modify1()
    foo.modify2()
    print(foo)
    
  • Programlama topluluklarında daha popüler tarz (bence).

Bir nesneyi mutasyon yapmanın artıları (hayır return self)

  • returnBaşka amaçlar için kullanabilme .
  • Guido van Rossum bu tarzı onaylar (Ben onun tartışmasına katılmıyorum).
  • Python topluluğunda daha popüler tarz (sanırım).
  • Varsayılan (daha az kaynak kodu).

Guido tartışması beni zorluyor. Özellikle, okuyucunun "yöntemlerin her birini yakından bilmesi gerekir" hakkında konuştuğu kısım, yani, sonunda ne olduğunu anlamadan önce, bunun bir öz zincir mi yoksa bir zincir mi, yoksa bir kombinasyon mu olduğunu belirlemeniz gerekir. zincir
Nath

@Nat Dize işleme işlemleri temelde işlemlerin geri kalanından ne kadar farklıdır?
16'da

Aradaki fark, dizenin sizin her seferinde tamamen farklı bir nesne oluşturduğudur. Yani Yerdeki öğeyi değiştirmemek. Mevcut nesnenin değiştirilmediği açıktır. Geri dönüşün örtülü olduğu bir dilde, bunun tersi doğrudur, ancak karışık ortam sorunlu gözükmektedir
Nath

@ Matt sadece Python dizelerinin değişmez olduğunu hatırladım. Bu tamamen sorumu cevaplıyor.
saat

1
@Matt "var olan nesnenin değiştirilmediği açıktır" - sadece görünüşe göre belli değil.
saat
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.