Python'un “yapmanın tek yolu” nun somut örnekleri maxim [kapalı]


34

Python'u öğreniyorum ve PEP 20 The Python Zen'de şu konuya ilgi duyuyorum :

Bunu yapmanın bir yolu ve tercihen sadece bir tane olmalı. Hollandalı olmadıkça bu yol ilk başta belli olmayabilir.

Herhangi biri bu maksimumın somut örneklerini sunabilir mi? Ruby gibi diğer dillerin aksine özellikle ilgileniyorum. Ruby tasarım felsefesinin bir parçası (Perl'den geliyor, sanırım?) Bunu yapmanın çoklu yollarının A Good Thing olduğu. Herhangi biri, her yaklaşımın artılarını ve eksilerini gösteren bazı örnekler sunabilir mi? Not, hangisinin daha iyi olduğu (muhtemelen hiç cevaplanamayacak kadar öznel) olan bir cevaptan sonra değil, iki tarzın tarafsız bir şekilde karşılaştırılması.

Yanıtlar:


47

Perl gibi dillerle karşılaştırıldığında Python'un sınırlı sayıda kontrol yapısı vardır:

  • Sadece ifve hiçbir unless,
  • sadece fordiziler üzerinde yinelenen ve hiç olmayan foreachveya C tarzı for,
  • Sadece whilebu her döngü ve hayır bir koşulu denetler do-while,
  • Sadece if-elifve hiçbir switch,
  • #Önceki satırlara bakmadan yorumlanacak tek bir yorum yapısı var ve yorumlanıp yorumlanamayacağını her satır için söyleyebilirsin.

Ayrıca, kaynağınızı girintinin neredeyse bir yolu var; çoğu yaratıcı girinti olgusu sözdizimsel olarak hariç tutulur.

Bu, bir Python kaynağının ayrıştırılmasını insanlar için kolaylaştırır.

Yerleşik türlerde ve standart kitaplıkta minimal ancak eksiksiz olma girişimleri vardır.

  • değişken listesi için yalnızca yerleşik listtürü kullanırsınız; çoğu işlem için O (1) 'dir ve asla doğru uygulamayı seçmek zorunda kalmazsınız,
  • değişmez listeler için, eşit olarak, yalnızca tupletürünü kullanın
  • Haritalar için, dictçoğu durumda oldukça etkili olan tek yerleşik ürünü kullanırsınız, hangi uygulamanın kullanılacağına karar vermenize gerek yoktur.

Python 3 bunu tam sayılara genişletir: tamsayınız ne kadar büyük olursa olsun, aynı türü kullanırsınız ve zorlama konusunda asla umursamazsınız.

Python, sözdizimsel şekeri önlemeye çalışır. Ancak bazen , bariz yolu belirginleştirmek için sözdizimsel şeker ekler. Bunun if foo is not Noneyerine yazabilirsiniz if not (foo is None)çünkü 'değil' özeldir. Yine de foo is not Nonekolayca okuyor, yanlış yorumlanamıyor ve düşünmek zorunda değilsiniz, sadece net olanı yazıyorsunuz.

Tabii ki, Python daha karmaşık şeylerin çoğu edebilir çeşitli şekillerde yapılabilir. Sınıflara bildirim yoluyla veya basit yuva ataması ile yöntemler ekleyebilir, çeşitli yaratıcı yöntemlerle işlevlere argümanları iletebilirsiniz.

Kilit nokta, her zaman en iyisi olması amaçlanan tek bir yolun olmasıdır, hepsi bu. Başka yollar varsa, eşit alternatifler olarak eklenmediler ( ifve ve gibi unless) değil, sadece içsel çalışmaları ortaya koyuyorlardı. Yavaş ama istikrarlı bir şekilde, bu gibi alternatifler bilinen en iyi mekanizmayı geliştirerek eski haline getirilir (yok edilmez!).

Dekoratörler AOP işlev çağrıları sararlar. 2.6'dan önce __metaclass__bir sınıfın metaclass'ını ilan etmek için magic üyeyi kullanmak zorundaydınız ; Şimdi bunun için de aynı dekoratör sözdizimini kullanabilirsiniz. 3.0'dan önce iki çeşit dizginiz vardı, bayt yönelimli ve yanlışlıkla karıştırabileceğiniz Unicode. Şimdi sadece Unicode strve bytesyanlışlıkla harmanlayamayacağınız ikili-saydam var .


3
Sadece bir not olarak, """yorumları unutma (dokümanlar). Bunlar birden fazla satıra yayılır.
asthasr

8
Üçlü alıntılar, sadece tekli alıntılarla aynıdır, ancak satır sonlarından kaçmadan çoklu satırları kapsarlar. Bildirimin hemen ardından bir dize değişmezi bir belge dizesi olarak kabul edilir ve bu bir yorum değildir, genellikle __doc__nitelik olarak erişilebilir . Ancak, dizeler Python'un kesinlikle birçok 'doğru yol' sağladığı bir alandır: tek, çift veya üçlü fiyat teklifi kullanın, dolaylı olarak bitişik kitaplara katılın, rham metinler için kullanın , vb.
9000

1
Ben syrion 'in yorumları ile ilgili edildi @ çünkü dizeleri " "" nin doğru değil, "her zaman bir çizgi sadece bakarak yorumladı olup olmadığını karar verebilir" düşünüyorum.
blubb

2
“Bu bir Python kaynağını ayrıştırmayı insanlar için kolaylaştırıyor.” <- bu öznel
jiggy 19

Metaclass bildirimi 2.7’de nasıl değişti? Dekoratör kalıbını metaclass için 2.7 belgede bulamıyorum.
Nick T,

10

Başka bir çift örnek:
len()Her sekansta mevcut olan bir metot yerine bir fonksiyondur; Eğer Java ile karşılaştırırsanız sahip .length, .size(), .getSize()bir dizideki öğe sayısını bulmak için, ve diğer yöntemler.

Başka bir örnek, .join()her sıradaki bir stringyöntem değil, bir yöntemdir. Join parametresinin bir liste mi, küme mi, anlama mı, yoksa ne işe yarayacağını bilmenize gerek yok.


8

C de bir değişkenin değerini birer birer arttırmanın birçok yolu vardır:

i++     // Post-increment, returns the number before the increment
++i     // Pre-increment, returns the number after the increment
i += 1 

Her değerini artırmak biter igöre 1, ancak her biraz farklıdır.

Python'da gerçekten tek bir yol var; sadece bir tane ekleyin.

i += 1

Ve bunu yapmanın birden fazla sözdizimsel olarak geçerli bir yolu olsa da (örneğin i = i + 1), aynı yan etkilerle aynı şeyi yapıyorsunuz.


1
Uzman değilim, ama bu örnek "bunu yapmanın tek yolu" fikrini kesin olarak ihlal ediyor gibi görünüyor. Bunu yapmak için iki yolumuz var, ama hangisi daha belirgin? Gözlerime göre ilk örnek daha açıkken, ikincisi biraz daha özlüdür, ancak temel bilgilerin ötesine geçen herhangi bir programcı için daha az okunabilir veya açık değildir. Cevabınız için teşekkürler - bu düşünce için iyi bir besindir.
Charles Roper

@Peter (ve @Charles): Aslında, i = i + 1bir artış değil atamadır. Python'da bir artış i += 1. C tarzı dillerde yazabilir i++, ++ive i += 1.
Josh K,

2
"Çok fazla karışıklık" yorumunuzdan emin değilsiniz, C örneklerinizin üçü de (kaçırdığınız i += 1, BTW) aynı sonucu veriyor . İnsanların kafasını karıştığını gördüğüm tek zaman, daha büyük bir ifadenin bir parçası olarak bir değişkeni ne zaman önceden yükselttiklerini veya sonra eklediklerini ve bu genellikle dil referansının uygun bölümünü okuyarak düzeltiliyor. Şahsen, bir dizgenin beşinci karakterine her ikisinin de str[4]ya da tarafından başvurabileceğiniz gerçeğini *(str+4)
seçmiştim

2
@TMN: Bazı durumlar, max(i++, ++i)hızlı bir şekilde düzeltilemez. C'nin pek çok "tanımsız" ve "uygulamaya bağlı" davranış durumu vardır, hepsi iyi bir sebepten dolayı - ancak her biri bir tuzak yaratabilir.
9000,

@TMN: 4 [str] 'dan bahsetmiyorum (C de geçerlidir, C ++' da geçerli olmayabilir).
Vatine,

6

Başka bir olasılık liste kavramaları olabilir. Python'da bunu yapabilirsiniz:

new_list = []
    for item in list_of_items:
       if item < 10:
           new_list.append(item)

Ancak bunu yapmanın "bariz" yolu (eğer Hollandalıysanız veya Python'u daha iyi tanıyorsanız), bunu bir liste kavrayışı ile yapabilirsiniz:

new_list = [item for item in list_of_items if item < 10]

Daha kısa, yeni liste bir adımda yaratılıyor, inanıyorum daha hızlı çalışıyor ve zarif. Dezavantajı ise, daha az açık hissettirdiği söylenebilir, ama bence alışırsanız, bu kadar açık.


Girinti ve kod için: 4 boşlukla hazırlayın, sonra girintiye saygı gösterecektir.
Inca,
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.