Python işlev çağrısında kullanılmayan dönüş parametreleri için kullanılacak stil


30

Bir işlevin bir değer dizisi döndürdüğü durumlar için işlenmesi önerilen / genel olarak kabul edilen bir kodlama stili var mı, ancak daha sonra bu değerlerden yalnızca biri kullanılıyor (bunun çoğunlukla değiştiremediğim kütüphane işlevleri için olduğunu unutmayın - etrafına bir sarmalayıcı yazma) çağrı muhtemelen fazladan bir parçadır…)? Yapmak yerine

a, b, c = foo()

ve sonra kullanmamak bve caşağıdaki değişkenlerden hangisinin tercih edilmesi gerektiği (veya başka bir tane var mı?):

Değişken 1 (alt çizgi)

a, _, _ = foo()

(çok açık ve basittir ancak _ = gettext.gettextçeviri kullanan birçok uygulamada kullanılanlarla çakışabilir)

Varyant 2 (sahte ad)

a, unused, unused = foo()

(çok çekici değil, sanırım, aynı diğer isimler için de geçerli dummy)

Değişken 3 (dizin)

a = foo()[0]

(bana göre ()[0]pitonik görünmüyor…)


Bu benim eski cevabımın tersine, şu an dönüş değerlerinin 2 / 3'üne atıf yapmak istediğinizde varyant 3 ile ne oluyor? Cevabımı kaldırdım çünkü Python hakkında haklı çıkarmak için yeterince bilgim olmadığını fark ettim.
Craige

@Craige: Cevabınızı çıkarmadan önce görmedim ... Çalışıp a, b = foo()[0:2]çalışmayacağını mı soruyorsunuz ? Eğer evet ise: evet, öyle :)
user49643

Tam olarak sorduğum buydu. Bu işe yararsa (söylediğiniz gibi) varyant 3'ü kullanırım. Bu bilgiyi verdiğim cevabımı tekrar yerleştiriyorum.
Craige

3
Bu arada, bu günlerde 'genişletilmiş' ambalajın açılması için oldukça güzel sözdizimini kullanabilirsiniz : a, *_ = foo()ilki dışındaki tüm değerleri atar.
Benjamin Hodgson

Yanıtlar:


17

Kullanılmayan değişkenler için alt çizgiyi kullanmak kesinlikle kabul edilebilir. Yine de, bazı kod tabanlarında, tanımlayıcı için kısayol olarak ayrıldığından bir seçenek değildir gettext. Bu, bu stile en çok itiraz (bu benim yargılayabildiğim kadarıyla çoğunluk için bir sorun değil). Yine de tavsiye ederim ve her zaman kendim kullanırım.

İsimler beni kişisel olarak rahatsız ediyor dummyya da unusedrahatsız ediyor, ve onları çok sık görmüyorum (Python'da, yani - dummyliberal olarak kullanan bir Delphi kod tabanı biliyorum ve aynı zamanda söz konusu programla ilişkilendirilmiş komut dosyalarına da sızdı). Sana karşı tavsiye ederim.

Sadece döndürülen diziden bir öğe çıkarmak da sorun değil. Aynı zamanda, kullanılmayan değerlerin sayısını doğru almakla güçlük kazandırır. İki potansiyel olumsuz yönü olduğunu unutmayın:

  • Değerlerin beklediğinizden farklı olması durumunda hava patlamaz. Bu , karışımları ve yazım hatalarını tespit etmek için yararlı olabilir .
  • Sadece dönüş değeri bir dizi olduğunda işe yarar (bu çoğunlukla tuples ve listeler, ancak genel olarak kalalım). Açıkçası, kodumda (2B vektör) yinelenebilir olan ve sabit sayıda değer veren (ve böylece paket açma atamalarında kullanılabilecek) bir sınıfı biliyorum, ancak dizine eklenemez.

Ben yaptım aslında neyse, cevabınızı kabul :) benim soru gettext sayılabilir - açık tek kabul tarzı olduğu görülmektedir ancak cevap bazı ilginç noktaları kaldırdı.
user49643,

Gettext ile ilgili sorunlardan kaçınmak için (veya tercümandaki benzer sorunlardan kaçınmak için), tek yerine çift alt çizgi (aka dunders) kullanabilirsiniz.
Zim

21

Pylint beni bu şekilde yapma alışkanlığına kavuşturdu:

widget, _parent, _children = f()

Yani, kullanılmayan sonuçların ön ekleri _ ile belirtilmiştir. Pylint, kullanılmamış olarak _ ile ön eklenmiş yerlileri ve _ ile private olarak _ ile ön eklenmiş küresel veya öznitelikleri dikkate alır.


3

Tüm projenizde, bunu sadece bir kez veya belirli bir işlevle nadiren yapıyorsanız gettext, bu modülde bir sorun olmadığını bildiğiniz takdirde Variant 1'i , aksi takdirde Variant 3'ü kullanırdım.

Öte yandan, eğer bunu çok yapıyor olsaydınız - ve özellikle her defasında farklı bir getiri değeri alt kümesi ( her seferinde geri dönüşü önemsemediklerinizi döndürmek için bir sarmalayıcı yapmak) istiyorsanız, bir sarmalayıcı yazmak faydalı olabilir. bu, sonuçları adlandırılmış bir dizgeye veya başka bir açıklayıcı sınıfın örneğine yerleştirir;

bar = foo()

Ve sonra çalışmak bar.a, bar.bve bar.c.


2

Diğerlerinin dediği gibi, underscore ( _) standarttır. Ancak, alt çizgi çeviriler için kullanılıyorsa, çift alt çizginin en iyi alternatif olduğunu düşünüyorum.

var, __, value = "VAR=value".partition('=')

Bunlardan daha iyi:

var, unused, value = "VAR=value".partition('=')

var, unused_del, value = "VAR=value".partition('=')

var, _del, value = "VAR=value".partition('=')


1

Ben Python olmayan bir programcıyım ama bana göre üçüncü değişken en mantıklı olanı.

Varyant 3'te, hangi değerlerle baş etmek istediğinize kesinlikle açıksınız. Varyant 1 ve 2'de, değerleri değişkenlere geri atarsınız ve böylece kullanılabilirler. Onları belirsiz bir şekilde adlandırmış olabilirsiniz, ancak zayıf adlandırma gerçekten herhangi bir soruna bir çözüm değildir.

Netlik dışında, neden kullanılmayan değerleri bellekteki bir yuvaya atamak isteyesiniz (varyant 1 ve 2'deki gibi)? Bu hafıza yönetimi açısından kötü bir çözüm olacaktır.


Her zaman aynı değişkene koyarsanız, bellek sorunu herhangi bir zamanda yalnızca tek bir değişkenin boyutunda olmaz mıydı? Bunun bir sorun olacağını sanmıyorum.
Michael McQuade

-2

İşte genel bir kural: Döndürülen değerlerden sadece 1 tanesi kullanılıyorsa, neden bu 1 değerini döndürmüyorsunuz? Bayrağın birden fazla yerden çağrılması durumunda, bayrağını aynı tutun ve bayrağa göre değerleri döndürün.

DÜZENLE:

Senin durumunda olsaydım ve fonksiyonu yazmasaydım, belki de Variant 2'yi seçerdim. Bir listeyi dilimlemek biraz ek yüke sahip olacaktır. Belki de istenmeyen verileri almak için birkaç bayt ayırabilirsiniz.


-1 Sanırım işlevi tanımlamamıştı ve bu yüzden ne döndürdüğünü değiştiremiyor. Bence fonksiyon 3 değer döndürdüğü zamandan bahseder, fakat şu anki kullanım durumunda sadece 1 umurunda.
Craige

@Craige: Evet, değiştiremediğim fonksiyonları kastediyordum - Sorumu açıklığa kavuşturmak için bir not ekledim.
user49643,

Havai olduğundan emin misin? Çok basit bir ipython testi denedim: %timeit a, _, _ = foo()vs. %timeit a = foo()[0]123ns ve 109ns sonuçlandı, yani dilimleme aslında paket açma değerinden daha hızlı görünüyor. Yoksa aklında belirli bir durum var mıydı?
user49643,

2
Başka bir olası senaryo, bazı çağrılar için tüm değerlere ihtiyaç duymamanızdır.
Keith Thompson,
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.