Python bu günlerde tüm öfke gibi görünüyor ve haklı olarak değil - çünkü gerçekten birisine çözmek için neredeyse yeni bir problem verilmekten hoşlandığı bir dil. Ama, bilge bir adam bir keresinde söylediği gibi (ona bilge bir adam = derken, sadece kimin söylediğine dair hiçbir fikrim yok çünkü o bilge olup olmadığından emin değilim hepsi), bir dili gerçekten bilmek, sadece sözdizimini, tasarımını, vb. avantajlarını değil, aynı zamanda dezavantajlarını da bilir. Hiçbir dil mükemmel değildir, bazıları diğerlerinden daha iyidir.
Peki, Python'un nesnel dezavantajları sizce ne olurdu.
Not: Burada bir dil karşılaştırması istemiyorum (yani C # Python çünkü ... yadda yadda yadda) - daha fazla hedef (belirli bir seviyeye) hangi dil özelliklerinin kötü bir şekilde tasarlandığını düşünün, belki neyi kaçırdığınızdan bazıları vb. Karşılaştırma olarak başka bir dil kullanmanız gerekiyorsa, ancak yalnızca aksi takdirde üzerinde durulması zor olan bir noktayı göstermek için (örn. anlayış kolaylığı)
Python biraz düzenli kullanıyorum ve genel olarak çok iyi bir dil olduğunu düşünüyorum. Bununla birlikte, hiçbir dil mükemmel değil. İşte benim için önem açısından dezavantajlar:
Yavaş. Gerçekten, gerçekten yavaş. Çoğu zaman bu önemli değil, ama kesinlikle bu performans açısından kritik bitler için başka bir dile ihtiyacınız olacak demektir.
Yuvalanmış işlevler, dış kapsamdaki değişkenleri değiştirememeniz gibi bir tür emicidir. Düzenleme: Hala kütüphane desteği nedeniyle Python 2 kullanıyorum ve bu tasarım kusuru benden rahatsız oluyor, ancak görünüşe göre Python --- yerel olmayan ifadesi nedeniyle. Kullandığım kütüphanelerin taşınmasını bekleyemem, böylece bu kusur tarihin kül yığınına iyi gönderilebilir.
Kütüphane/genel kod için yararlı olabilecek birkaç özellik eksik ve IMHO sağlıksız uçlara götürülen basitlik. Düşünebileceğim en önemli olanlar kullanıcı tanımlı değer türleridir (bunların metasınıf büyüsü ile oluşturulabileceğini tahmin ediyorum, ancak hiç denemedim) ve ref işlevi parametresi.
Metalden uzak. İş parçacığı ilkelleri veya çekirdek kodu veya başka bir şey yazmanız mı gerekiyor? İyi şanslar.
Python sunduğu dinamikler için bir takas olarak anlamsal hataları yakalama yeteneğinin eksikliği umursamıyorum, keşke bir yolu olsaydı sözdizimsel hataları ve kodu gerçekten çalıştırmak zorunda kalmadan değişken adlarının yanlış yazılması gibi aptalca şeyler yakalamak.
Belgeler, güçlü kurumsal destekleri olan PHP ve Java) gibi diller kadar iyi değildir.
Python bir değişkenin bildirimi ve kullanımı arasında ayrım yapamayacağından nefret ediyorum. Bunu yapmak için statik yazmaya ihtiyacınız yok. kasten beyan ettiğim bir değişkendir ve ben niyet yeni bir ad tanıtmak için bu bir yazım hatası değildir ”.
Ayrıca, genellikle Python değişkenleri bir kez yazma stilinde kullanıyorum, yani, değişkenleri değişmez olarak ele alıyorum ve ilk atamalarından sonra değiştirmiyorum. Liste kavraması gibi özellikler sayesinde , bu gerçekten inanılmaz derecede kolaydır ve kod akışını takip etmeyi daha kolay hale getirir.
Ancak, bu gerçeği belgeleyemiyorum. Python içindeki hiçbir şey değişkenlerin üzerine yazmamı veya değişkenleri yeniden kullanmamı engelliyor.
Özetle, dilde iki anahtar kelime istiyorum: var
ve let
. Bunlardan herhangi biri tarafından bildirilmeyen bir değişkene yazarsam, Python bir hata ortaya çıkarmalıdır. Ayrıca, let
değişkenleri salt okunur olarak bildirirken var
değişkenler “normal” dir.
Bu örneği düşünün:
x = 42 # Error: Variable `x` undeclared
var x = 1 # OK: Declares `x` and assigns a value.
x = 42 # OK: `x` is declared and mutable.
var x = 2 # Error: Redeclaration of existing variable `x`
let y # Error: Declaration of read-only variable `y` without value
let y = 5 # OK: Declares `y` as read-only and assigns a value.
y = 23 # Error: Variable `y` is read-only
Türlerin hala örtük olduğuna dikkat edin (ancak let
değişkenleri, yeni bir değere geri yüklenemedikleri için statik olarak yazılan tüm niyetler ve amaçlar içindir; var
değişkenleri yine de dinamik olarak girilebilir).
Son olarak, tüm yöntem bağımsız değişkenleri otomatik olarak let
olmalıdır, yani salt okunur olmalıdır. Genel olarak, aşağıdaki deyim dışında bir parametreyi değiştirmek için iyi bir neden yoktur:
def foo(bar = None):
if bar == None: bar = [1, 2, 3]
Bunun yerini biraz farklı bir deyim alabilir:
def foo(bar = None):
let mybar = bar or [1, 2, 3]
Ana şikayetim, küresel yorumlayıcı kilidi nedeniyle birçok durumda (Java, C ve diğerlerine kıyasla) performans göstermeyen (bkz. "Inside Python GIL") (PDF bağlantısı) tartışma)
Bununla birlikte, kullanımı çok kolay olan bir çoklu işlem arabirimi vardır, ancak aynı sayıda işlem için bellek kullanımı üzerinde daha ağır veya çok fazla paylaşılan verileriniz varsa zor olacaktır. . Bununla birlikte, birden fazla işlemle çalışan bir programınız olduğunda, dişli bir programın yapamayacağı birçok makinede ölçeklenebilir.
Belgelerin eleştirisine gerçekten katılmıyorum, orada tüm büyük diller olmasa bile mükemmel ve çoğundan daha iyi olduğunu düşünüyorum.
Ayrıca çalışan çalışma zamanı hatalarının çoğunu yakalayabilirsiniz pylint .
Tartışmalı, çalışma zamanı hatalarının belirli sınıflarını tanıtabilecek statik yazmanın olmaması, ördek yazmanın sağladığı ek esnekliğe değmez.
Sanırım Python 'un nesne yönelimli kısımları bir tür "cıvatalı" hissediyorum. Her yönteme açıkça "öz" iletme ihtiyacı, OOP bileşeninin açıkça planlanmadığı olduğunu belirten bir belirtidir; ayrıca Python'un bazen başka bir cevapta eleştirilen siğil kapsam belirleme kurallarını gösterir.
Düzenleme:
Python'un nesne yönelimli parçalarının "cıvatalı" olduğunu söylediğimde, zaman zaman OOP tarafının oldukça tutarsız olduğunu hissediyorum. Ruby'yi ele alalım, örneğin: Ruby'de, her şey bir nesnedir ve tanıdık obj.method
Sözdizimini (aşırı yüklenmiş işleçler hariç) kullanarak Tabii ki); Python'da her şey bir nesnedir, ancak işlev olarak adlandırdığınız bazı yöntemler; yani, bir uzunluğu döndürmek için __len__
'a aşırı yüklenirsiniz, ancak diğer dillerde daha yaygın (ve tutarlı) obj.length
yerine len(obj)
kullanarak çağırın. Bu tasarım kararının arkasında nedenler olduğunu biliyorum, ama onları sevmiyorum.
Ayrıca, Python'un OOP modeli herhangi bir veri korumasından yoksundur, yani özel, korunan ve herkese açık üye yoktur; yöntemlerin önünde _
ve __
kullanarak onları taklit edebilirsiniz, ancak bu biraz çirkin. Benzer şekilde, Python da tam olarak OOP 'un mesaj iletme özelliğini de sağlamaz.
Python hakkında sevmediğim şeyler:
lambda
yalnızca bir ifade içerebilir).cin
veya scanf
gibi veya Java'daki Scanner
gibi).Değişken veri türlerine sahip varsayılan bağımsız değişkenler.
def foo(a, L = []):
L.append(a)
print L
>>> foo(1)
[1]
>>> foo(2)
[1, 2]
Genellikle bazı ince hataların sonucudur. Varsayılan bir argüman gerektiğinde (her işlev çağrısı için kullanılacak tek bir nesne oluşturmak yerine) yeni bir liste nesnesi oluştursaydı daha iyi olacağını düşünüyorum.
Edit: Bu büyük bir sorun değil, ama bir şey dokümanlar sevk edilmesi gerektiğinde, bu genellikle bir sorun anlamına gelir. Bu gerekli olmamalı.
def foo(a, L = None):
if L is None:
L = []
...
Özellikle de bunun varsayılan olması gerektiğinde. Beklediğinizle eşleşmeyen ve çok sayıda koşul için kullanışlı olmayan garip bir davranış.
Python'un onu geliştirme dili kadar esnek kılan özelliklerinden bazıları, C++ ve Java gibi dillerde derleme ve bağlama işlemi tarafından yürütülen "tüm program" statik analizinde kullanılanlar tarafından büyük dezavantajlar olarak görülmektedir.
Yerel değişkenler normal atama ifadesi kullanılarak bildirilir. Bu, başka bir kapsamdaki değişken bağların derleyici tarafından açık bir ek açıklama gerektirdiğini gösterir (dış kapsamlar için küresel ve yerel olmayan bildirimler, örneğin kapsamlar için öznitelik erişim gösterimi). Bu, programlama sırasında ihtiyaç duyulan kazan plakası miktarını büyük ölçüde azaltır, ancak derleyici tarafından açık değişken bildirimleri gerektiren dillerde yapılan kontrolleri gerçekleştirmek için üçüncü taraf statik analiz araçlarına (pyflakes gibi) ihtiyaç duyulduğu anlamına gelir.
Modüllerin, sınıf nesnelerinin ve hatta yerleşik ad alanının içeriği çalışma zamanında değiştirilebilir. Bu, son derece kullanışlı tekniklere izin veren son derece güçlüdür. Ancak, bu esneklik Python, statik olarak yazılan OO diller için ortak bazı özellikler sunmadığı anlamına gelir. En önemlisi, örnek yöntemlerine yönelik "self" parametresi açıktır) örtük olmak yerine ("yöntemler" bir sınıf içinde tanımlanmaları gerekmediğinden, daha sonra sınıfı değiştirerek eklenebilirler, yani örnek başvurusunu örtük olarak iletmenin özellikle pratik olmadığı anlamına gelir) ve öznitelik erişim denetimleri ' t Kodun sınıfın "içinde" veya "dışında" olup olmadığına bağlı olarak kolayca uygulanır (bu ayrım yalnızca sınıf tanımı yürütülürken geçerlidir).
Bu, diğer birçok üst düzey dil için de geçerlidir, ancak Python çoğu donanım detayını soyutlama eğilimindedir. C ve C++ gibi sistem programlama dilleri hala doğrudan donanım erişimini işlemek için çok daha uygundur (ancak, Python, CPython genişletme modülleri veya daha taşınabilir bir şekilde ctypes
kitaplığı aracılığıyla bunlarla mutlu bir şekilde konuşacaktır).
Kırık kapsam belirleme örneği; tercüman oturumundan konuşma metni:
>>> x=0
>>> def f():
... x+=3
... print x
...
>>> f()
Traceback (most recent call last):
File "", line 1, in ?
File "", line 2, in f
UnboundLocalError: local variable 'x' referenced before assignment
Bu tasarım aptallığını düzeltmek için global
ve nonlocal
anahtar kelimeleri eklendi.
Python'un nesne yönelimli this.method()
ve yordamsal/fonksiyonel method(this)
sözdizimini çok rahatsız edici buluyorum:
x = [0, 1, 2, 3, 4]
x.count(1)
len(x)
any(x)
x.reverse()
reversed(x)
x.sort()
sorted(x)
Bu özellikle kötüdür çünkü çok sayıda işlev (yöntemlerden ziyade) global ad alanı : listeler, dizeler, sayılar, yapıcılar, metaprogramlama ile ilgili yöntemler, hepsi tek bir büyük alfabetik sıralı liste.
En azından, F # gibi fonksiyonel diller tüm işlevlerde modüllerde düzgün bir şekilde adlandırılmıştır:
List.map(x)
List.reversed(x)
List.any(x)
Yani hepsi bir arada değil. Dahası, bu kütüphane boyunca takip edilen bir standarttır, bu yüzden en azından tutarlıdır.
işlev vs yöntemi şey yapma nedenlerini anlıyorum, ama ben hala bu şekilde karıştırmanın kötü bir fikir olduğunu düşünüyorum. En azından ortak işlemler için yöntem-sözdizimi izlenirse çok daha mutlu olurum:
x.count(1)
x.len()
x.any()
x.reverse()
x.reversed()
x.sort()
x.sorted()
Yöntemlerin mutasyon geçirip geçirmediği, nesne üzerinde yöntem olarak kullanılmasının birkaç avantajı vardır:
Module.method(x)
çağrılırken Module
ifadesini tekrarlamaya gerek yoktur. Yukarıdaki işlevsel Liste örneğini göz önünde bulundurarak, neden List
ifadesini tekrar tekrar söylemeye devam etmem gerekiyor? Bunun bir List
olduğunu bilmeli ve üzerinde Navigation.map()
fonksiyonunu çağırmak istemiyorum! x.map()
sözdizimini kullanmak DRY ve hala açık.Ve elbette global-isim-alanına- koyma yöntemine göre avantajları vardır. Mevcut yolun işlerin yapılmasını aciz olmadığı anlamına gelmez. Hiçbir şey isim aralıklı olmadığından, oldukça kısa (len(lst)
) bile! Yöntemler üzerinde işlevlerin (varsayılan davranış vb.) Kullanılmasının avantajlarını anlıyorum, ancak yine de sevmiyorum.
Sadece dağınık. Ve büyük projelerde, dağınıklık en büyük düşmanınızdır.
homoikonisite eksikliği.
Python'un "with" anahtar kelimesi eklemek için 3.x beklemesi gerekiyordu. Herhangi bir homoikonik dilde önemsiz bir şekilde bir kütüphaneye eklenmiş olabilir.
Cevaplarda gördüğüm diğer sorunların çoğu 3 türden biridir:
1) Aletle sabitlenebilecek şeyler (örn. Pyflakes) 2) Uygulama detayları (GIL, performans) 3) Kodlama standartlarına göre düzeltilebilen şeyler (yani insanların orada olmasını istemediği özellikler)
# 2, dil ile ilgili bir sorun değil, IMO # 1 ve # 3 ciddi sorunlar değil.
Python, çok etkileyici olduğu için en sevdiğim dildir, ancak yine de çok fazla hata yapmanıza engel olur. Hala beni rahatsız eden birkaç şey var:
Gerçek anonim işlev yok. Lambda tek deyimli işlevler için kullanılabilir ve with
deyimi Ruby'de bir kod bloğu kullanacağınız birçok şey için kullanılabilir. Ancak bazı durumlarda işleri olması gerekenden biraz daha beceriksiz hale getirir. (Java'da olduğu kadar beceriksiz olmaktan uzak, ama yine de ...)
Modüller ve dosyalar arasındaki ilişkide biraz karışıklık var. Komut satırından "python foo.py" komutunu çalıştırmak "import foo" komutundan farklıdır. Python 2.x içindeki göreli ithalat da sorunlara neden olabilir. Yine de, Python'un modülleri C, C++ ve Ruby'nin ilgili özelliklerinden çok daha iyidir.
Açık self
. Bunun nedenlerinden bazılarını anlasam da ve Python günlük kullanmama rağmen, bunu unutmakla hata yapıyorum). açık benlik, başkalarının şikayet ettiği sınırlı kapsamla ilgilidir. Python içindeki en küçük kapsam fonksiyon kapsamıdır. gerekir, bu kendi başına bir sorun değildir ve IMO genellikle daha temiz kod verir.
Bir yöntem olmasını beklediğiniz len
gibi bazı global işlevler (aslında sahne arkasında).
Önemli girinti. Harika olduğunu düşündüğüm fikrin kendisi değil, ama bu kadar çok insanın Python'u denemesini engelleyen tek şey olduğundan, belki Python bazı (isteğe bağlı) başlangıç / bitiş ile daha iyi olurdu Bu insanları görmezden gelerek, girinti için de zorla bir bedenle yaşayabilirdim.
JavaScript yerine web tarayıcılarının yerleşik dili olmadığını.
Bu şikayetlerden, dilde eklenmesi gerektiğini düşündüğüm kadar önem verdiğim ilk ilki. Diğeri, sonuncusu hariç, oldukça küçüktür, ki bu olsaydı harika olurdu!
Python tam olarak olgunlaşmamış: python 3.2 dil şu anda dağıtılan paketlerin çoğu ile uyumluluk sorunlarına sahip (genellikle python 2.5) Bu, şu anda daha fazla geliştirme çabası gerektiren büyük bir dezavantajdır (gerekli paketi bulun; uyumluluğu doğrulayın; daha uyumlu olabilecek iyi olmayan bir paket seçerek tartın; en iyi sürümü alın, alabilecek 3.2'ye güncelleyin sonra yararlı bir şey yapmaya başlayın).
2012 ortalarında bu bir dezavantaj olacaktır.
Sanırım bir fan-boy tarafından reddedildim. Bir geliştirici tartışması sırasında üst düzey geliştirici ekibimiz de aynı sonuca vardı.
Bir anlamda olgunluk, bir ekibin teknolojiyi kullanabileceği ve gizli riskler olmadan (uyumluluk sorunları dahil) çok hızlı bir şekilde çalışabileceği anlamına gelir. 3. taraf python paketler ve birçok uygulama bugün paketlerin çoğunluğu için 3.2 altında çalışmaz. = daha az olgun teknoloji.
Haziran 2013 Güncellemesi: Python 3 hala olgunluk sorunları yaşıyor. Her zaman bir takım üyesi gerekli bir paketten bahseder ve sonra "sadece 2.6 hariç" deyin (bu durumlarda ben 2.6 ile yalnızca 2.6 paketini kullanmak için localhost soketi aracılığıyla bir çözüm uyguladık ve araçlarımızın geri kalanı 3.2 ile kalıyor) Saf python wiki olan MoinMoin bile Python = 3.
Python'un kapsamı çok bozuk, bu da Python) içinde nesne yönelimli programlamayı çok zorlaştırıyor.
Python] içindeki erişim değiştiricileri uygulanamaz - iyi yapılandırılmış, modüler kod yazmayı zorlaştırır.
Sanırım bu @ Mason'un kırık kapsamının bir parçası - genel olarak bu dilde büyük bir sorun. Okunabilir olması gereken kod için, kapsamda ne olabileceğini ve ne olması gerektiğini ve herhangi bir zamanda bir değerin ne olacağını anlamak oldukça zor görünüyor - Şu anda Python dil.
"Hepimiz yetişkinleri onaylıyoruz", özellikle karmaşık projeler üzerinde çalışırken hata yapmadığımız ve güçlü bir yapıda daha iyi çalışmadığımız anlamına gelmez - girinti ve anlamsız alt çizgiler yeterli görünmüyor .
Python hakkındaki düşüncelerim:
Çoklu gönderim, yerleşik tek gönderim tipi sistemle iyi bir şekilde bütünleşmez ve çok iyi performans göstermez.
Dinamik yükleme, POSIX benzeri anlambilimin meta veri yoğun işlemler için yıkıcı yavaşlamalara yol açtığı paralel dosya sistemlerinde büyük bir sorundur. Ben çeyrek milyon çekirdek saat yaktı meslektaşlarım var sadece Python (numpy, mpi4py, petsc4py ve diğer uzatma modülleri ile) 65k çekirdek yüklü. (Simülasyon önemli bir yeni bilim verdi sonuç, buna değdi, ancak bir varilden fazla petrolün yüklenmesi için yakılması bir sorundur Python bir kez.) Statik olarak bağlanamaması bizi büyük sıkıntılara gitmeye zorladı dlopen
toplu dosya sistemi erişimini gerçekleştirmek için libc-rtld düzeltme eki dahil olmak üzere, makul yükleme sürelerini ölçeklendirin.
Her neyse, python 4 yıldır benim ana dilim. Fanboylar, elitistler veya monomanyak olmak python kültürünün bir parçası değil.
Ben iyilik python ve aklıma gelen ilk dezavantaj if myTest():
gibi bir ifade yorum yaparken o zaman sen yürütmek tüm yürütme bloğunun girintisini değiştirmek gerekir C veya Java ile ilgisi yoktur. Aslında python yerine if-cümlesi hakkında yorum yapmak yerine bunu şu şekilde yorumlamaya başladım: `if True: #myTest ( ) Bu yüzden de aşağıdaki kod bloğunu değiştirmek zorunda kalmayacaksınız. Java ve C girintiye güvenmediğinden C ve Java ile açıklamaları yorumlamayı kolaylaştırır.
Ancak bazı harika itfa özellikleri var:
len(s)
ila __len__(self)
ve diğer "özel yöntemler"__add__
ve __iadd__
için +
ve +=
)self
ilk yöntem parametresi olarak"Değişmezlik" tam olarak güçlü bir nokta değil. AFAIK sayıları, tuples ve dizeler değişmezdir, diğer her şey (yani nesneler) değiştirilebilir. Bunu Erlang veya Haskell gibi her şeyin değişmez olduğu fonksiyonel dillerle karşılaştırın (varsayılan olarak, en azından).
Bununla birlikte, Dokunulmazlık gerçekten de Python'un güçlü noktası olmayan eşzamanlılık * ile parlıyor, bu yüzden en azından sonuç.
(* = Nitpickers için: En azından kısmen paralel olan eşzamanlılık demek istiyorum. Sanırım Python değişmezliğin önemli olmadığı "tek iş parçacıklı" eşzamanlılık ile tamam. (Evet, FP severler, eşzamanlılık olmadan bile değişmezliğin harika olduğunu biliyorum.))
Açıkça paralel yapılara sahip olmak isterim. Daha sık olmamakla birlikte,
[ f(x) for x in lots_of_sx ]
Elemanların işlenme sırasını umursamıyorum. Bazen, hangi sırayla iade edildiklerini bile umursamıyorum.
CPython benim f saf Python olduğunda iyi yapamasanız bile, diğer uygulamalar için bu gibi bir davranış tanımlanabilir.
Python'un çoğunlukla felsefi nedenlerle nedeniyle kuyruk çağrısı optimizasyonu yoktur. Bu, büyük yapılarda kuyruk yinelemenin O(n) belleğe mal olabileceği (tutulan gereksiz yığın nedeniyle) ve O(1) bellek.