If-return-return veya if-else-return kullanmak daha verimlidir?


141

Bir olduğunu varsayalım ifbir beyanına return. Verimlilik açısından, kullanmalıyım

if(A > B):
    return A+1
return A-1

veya

if(A > B):
    return A+1
else:
    return A-1

Derlenmiş bir dili (C) veya yazılı bir dili (Python) kullanırken birini mi yoksa diğerini mi tercih etmeliyim?


11
Derlenmiş bir dilde verimlilik konusunda fazla endişelenmenize gerek yok. Derleyici bunu sıralar. Kodunuzu okuyabilmeniz için yazmalısınız. (Hala algoritmalarınızın verimliliği konusunda endişelenmeniz gerekiyor ve türlerin özensiz kullanımı vb. Verimliliği etkileyecektir - sadece tarzınız hakkında çok fazla endişelenmiyorsunuz.) Python'u bilmiyorum.
ams

5
Kodunuzu sıralamak için derleyicinize güvenmek tehlikeli bir adımdır ve yanılmaz bir derleyici gerektirir. Eğer whay tou kodunu yapmak istiyorsan daha iyi!
Andrew

1
Yaptığınız şey spec tarafından tanımlanmışsa, derleyiciden şüphe etmek için herhangi bir neden olduğuna inanmıyorum. Sizden çok daha zeki insanlar olarak yazılmış olacak ve onlardan bir hata yapmanız çok daha muhtemel.
will

7
Bu fikir temelli olarak nasıl kapatılabilir? İkisi arasında performans farkı olmadığını öğrendikten sonra bir görüş olabilir . Ben yapmadım ve pek çok insanın da yapmadığından eminim.
Jorge Leitao

1
Soru oldukça popüler olsa da, belirli bir dil düşünülmeden doğru bir şekilde cevaplanamaz, aksi takdirde her dil için cevap vermek bu format için çok uzun olacaktır.
Emile Bergeron

Yanıtlar:


195

Yana returnifadesi çalışmakta olan işlevi sonlandırır (ikincisi muhtemelen daha okunabilir ilk daha olmasına rağmen) iki form eşdeğerdir.

Her iki formun verimliliği karşılaştırılabilir, altta yatan makine kodu, ifkoşul yine de yanlışsa bir atlama gerçekleştirmelidir .

Python'un durumunuzda yalnızca bir returnifade kullanmanıza izin veren bir sözdizimini desteklediğini unutmayın :

return A+1 if A > B else A-1

32
C de bunu destekliyor. return (A>B)?A+1:A-1;Bununla birlikte , kodun bu şekilde yazılmasından kesinlikle bir performans kazancı yoktur . Elde ettiğimiz tek şey, kodu gizlenmiş, okunamayan ve bazı durumlarda örtük tür tanıtımlarına karşı daha savunmasız hale getirmektir.
Lundin

47
@Lundin gizlendi mi? okunmaz? Sadece üçlü operatörü bilmeyenler için.
glglgl

6
@Lundin Bu argümanı takiben <kötü bir uygulamadır, çünkü -1 < 1ubeklenmedik bir sonuç doğurur.
glglgl

3
@glglgl: Hayır, çünkü insanlar?: operatörünün if-else gibi davranmasını bekler, ki bu doğru değildir. Birisi gibi kod yazacak olsaydı -1 < 1u, şüpheliyim, kolayca hata tespit ederdim. Oldukça fazla insan ben ancak kodun bazı sürümünü yazmak istiyorsunuz. Bu tür hataları üretim kodunda?: Operatörüne güvenmek için çok sık gördüm. Ayrıca, bir kural olarak, dil size aynı şeyi yapmanın iki farklı yolunu verirse, bunlardan sadece birini kullanın, ruh halinize bağlı olarak ikisinden birini rastgele seçmeyin.
Lundin

6
@Lundin, C? 'De dikkatli olmanın bir argümanıdır, ancak bunun Python için de geçerli olduğunu söylüyorsunuz. Python'da üçlü kullanmanın beklenmedik sonuçlara yol açtığı herhangi bir örneğe işaret edebilir misiniz?
lvc

33

Gönderen Chromium'un stil kılavuzu:

Dönüşten sonra başka kullanmayın:

# Bad
if (foo)
  return 1
else
  return 2

# Good
if (foo)
  return 1
return 2

return 1 if foo else 2

1
Teşekkürler. +1. Geri döndükten sonra neden başka bir şey kullanmadığını sorabilir miyim?
Tim

1
if-else işlevsel olarak eşdeğerdir, ancak ayrıntılıdır. Diğeri gereksiz.
skeller88

17
Şaşırdım çünkü birincisi daha net ve daha iyi görünüyor.
Tim

4
İkisi için de makul bir dava açabilirsiniz. Bu karar IMO'sundaki en önemli şey, kod tabanı içinde tutarlı olmaktır.
skeller88

2
Muhtemelen vakaların çoğunda if-else-returndalların neredeyse hiç eşit olmadığını göreceksiniz (eğer öyleyse, yine de yeniden düzenlemelisiniz; ya bir switchyapı kullanarak veya Python için, bir diksiyon numaralandıran / çağrılabilir / vb kullanarak). Bu nedenle hemen hemen hepsi if-else-returnkoruma cümleleri ve bunlar her zaman test edilebilir (test edilen ifadeyle alay et) else.
Ocak 18

5

Kodlama stili ile ilgili:

Dil ne olursa olsun çoğu kodlama standardı, birden fazla dönüş ifadesini tek bir işlevden kötü uygulama olarak yasaklar.

(Her ne kadar kişisel olarak, birden çok dönüş ifadesinin mantıklı olduğu birkaç durum olduğunu söyleyebilirim: metin / veri protokolü ayrıştırıcıları, kapsamlı hata işleme gibi işlevler vb.)

Tüm bu endüstri kodlama standartlarının fikir birliği, ifadenin şu şekilde yazılması gerektiğidir:

int result;

if(A > B)
{
  result = A+1;
}
else
{
  result = A-1;
}
return result;

Verimlilik ile ilgili olarak:

Yukarıdaki örnek ve sorudaki iki örnek , verimlilik açısından tamamen eşdeğerdir . Tüm bu durumlarda makine kodu A> B'yi karşılaştırmalı, daha sonra A + 1 veya A-1 hesaplamasına dallamalı ve bunun sonucunu bir CPU kaydında veya yığınta saklamalıdır.

DÜZENLE :

Kaynaklar:

  • MISRA-C: 2004 kuralı 14.7, ki bu da alıntıdır ...:
  • IEC 61508-3. Bölüm 3, tablo B.9.
  • IEC 61508-7. C.2.9.

37
Tek dönüşlü dinin çoğu kodlama standardını etkilediğinden emin misiniz? Bu korkutucu olurdu.
Daniel Fischer

7
Kuralın çoğu zaman mantıklı olmadığını söyleyebilirim. Kodu daha okunaklı ve uygun noktalardaki iadelerle takip etmeyi daha kolay bulma eğilimindeyim. Ama bu sadece benim. Bununla birlikte, şirket / proje kodlama standartlarını düşündüm, aksi takdirde aptal reçetelerin zaman zaman bazı avantajları olabileceği MISRA gibi şeyler değil. Umarım çoğu tek çıkış noktası fikrini almamıştır.
Daniel Fischer

3
@DanielFischer: Şirketim için tasarladığım MISRA'ya dayanan C kodlama standardında, "Bir fonksiyonun sonunda, tek bir çıkış noktası kodu yapmadığı sürece, bir fonksiyonun sonunda tek bir çıkış noktası olacaktır. daha az okunabilir ". Yani MISRA-C ama kuralın dışında. Geri dönebilen gelişmiş bir ayrıştırıcı işlevi yazarsanız, 10 farklı hatayı diyelim, iç içe parantez düzeyi kodu tamamen okunamaz hale getirir - bu durumda bir hatayla karşılaşıldığında hemen geri dönmek daha mantıklı olur.
Lundin

6
Bir tartışma ve tek çıkış noktası konusunda daha fazla tartışma için bu SO sorusuna bakın . Tek çıkış noktası kuralının eski moda ve aşırı "mühendislik" olmasının yanı sıra, Python özellikle "düz iç içe olmaktan daha iyidir" görüşünü teşvik eder ve net olduğu return her yere koymak Python'da bunu yapmanın deyimsel yoludur.
John Y

1
@percebus Tamamen katılıyorum ve siklomatik karmaşıklık tek geri dönüşe karşı iyi bir argüman. MISRA komitesini bu konudan birkaç kez dile getiriyorum, mesela buna bakın . En azından kural, MISRA-C: 2012'de danışmanlığa indirildi.
Lundin

3

Herhangi bir mantıklı derleyici ile, hiçbir fark gözlemlememelisiniz; eşdeğer oldukları için aynı makine koduna derlenmelidirler.


2

Tercüman umurunda olmadığı için bu bir stil (veya tercih) meselesidir. Şahsen ben, fonksiyon tabanı dışında bir girinti düzeyinde bir değer döndüren bir fonksiyonun son ifadesini yapmamaya çalışırdım. Örnek 1 'deki diğer, fonksiyonun sonunun olduğu yerde, sadece hafifçe gizlenir.

Tercihen şunu kullanıyorum:

return A+1 if (A > B) else A-1

Hem fonksiyondaki son ifade olarak (daha önce de belirtildiği gibi) tek bir dönüş ifadesine sahip olmanın iyi kuralına hem de zorunlu stil ara sonuçlarından kaçınmanın iyi fonksiyonel programlama paradigmasına uymaktadır.

Daha karmaşık işlevler için, mümkünse erken dönüşleri önlemek için işlevi birden çok alt işleve ayırmayı tercih ederim. Aksi takdirde rval denilen bir zorunlu stil değişkeni kullanmaya dönüyorum. İşlev önemsiz değilse veya sondan önce döndürme ifadesi bir hata sonucu olmadığı sürece birden fazla dönüş ifadesi kullanmamaya çalışıyorum. Zamanından önce dönmek, devam edemeyeceğinizi vurgular. Birden çok alt işleve dallanmak üzere tasarlanmış karmaşık işlevler için bunları vaka ifadeleri olarak kodlamaya çalışırım (örneğin bir dikte ile çalıştırılır).

Bazı posterlerde çalışma hızından bahsedildi. Yürütme hızı benim için ikincil çünkü yürütme hızına ihtiyacınız varsa Python kullanmak için en iyi dil değil. Python benim için önemli olan kodlama (yani hatasız kod yazma) verimliliği olarak kullanın.


1
Bir kullanıcı cevabımı aşağı oylayacaksa, neden yanlış olduğumu düşündüğü konusunda bir yorum yapmaktan memnuniyet duyarım.
Stephen Ellwood

Muhtemelen okunabilirlik amacıyla ifade başına 1 satır yapmak için sadece bir satır olurdu. var n = 1 if (A > B) else -1 return A+n
percebus

@percebus bazı durumlarda değişken adının anlamı geliştirip geliştiremeyeceğini kabul ediyorum. Örneğin: 'kod' move_x = 1 eğer my_x <rakip_x başka -1 # rakibe doğru hareket ederse
Stephen Ellwood

BTW Aslında cevabınızı iptal ettim. Cevabımın oldukça benzer olduğunu görürseniz
percebus

2

elseMümkün olduğunda şahsen bloklardan kaçınırım . Bkz Karşıtı eğer Kampanyası

Ayrıca, hat için 'ekstra' ücret almazlar, bilirsiniz: p

"Basit karmaşık olmaktan iyidir" & "Okunabilirlik kraldır"

delta = 1 if (A > B) else -1
return A + delta

2
Neden aşağı oy? 'Pitonik' bir cevaptır. Bunun tercih edilen bir cevap olduğunu düşünmeyebilirsiniz. Ancak geçersiz değil. Ayrıca KISS Prensibi takip ediyorum en.wikipedia.org/wiki/KISS_principle
percebus

3
Cevabınızı onayladım, çünkü benim için okunabilirlik ve basit puanlar. Şahsen saldırganın, cevabımın neden aktif olarak olumsuz olduğu konusunda beni eğitmeden beni oyladığını düşünüyorum.
Stephen Ellwood

1
Anti-if kampanyasını daha önce duymadım, ancak if'lerin neden tehlikeli olabileceğini anlayabildi. Her zaman bir if ifadesi tarafından çevrelenen kod miktarını sınırlamaya ve elif ağaçlarını dikte kullanmak için yeniden yazmaya çalışıyorum. Bu biraz konu dışı oluyor.
Stephen Ellwood

1
@StephenEllwood Diffs dictönlemek için s kullanmak performans açısından çok kötü bir fikirdir.
Bachsau

@Bachsau Muhtemelen haklısın. Tüm komut dosyalarım saniyeler içinde çalıştığı için performans konusunda hiç endişelenmem gerekmedi. Benim için okunabilirlik genellikle performansı düşürür. Tam zamanlı bir programcı olmadığım için; onlar sadece bir amaç için araçlar.
Stephen Ellwood

1

A sürümü daha basit ve bu yüzden kullanacağım.

Java'daki tüm derleyici uyarılarını açarsanız, ikinci Sürüm'de bir uyarı alırsınız, çünkü gereksizdir ve kod karmaşıklığını artırır.


1

Sorunun python olarak etiketlendiğini biliyorum, ancak dinamik dillerden bahsediyor, bu yüzden yakutta if ifadesinin aslında bir dönüş türü olduğunu belirtmeliyim, böylece böyle bir şey yapabilirsiniz

def foo
  rv = if (A > B)
         A+1
       else
         A-1
       end
  return rv 
end

Ya da sadece örtülü dönüşü olduğu için

def foo 
  if (A>B)
    A+1
  else 
    A-1
  end
end

Bu da oldukça güzel bir şekilde birden fazla geri dönüşe sahip olmama tarzı sorununu ele alıyor.

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.