Neden Python'da ++ ve - operatörleri yok?


Yanıtlar:


443

Mantıklı olmadığı için değil; "x ++" ifadesini "x + = 1" olarak tanımlamak ve önceki x "bağlamasını değerlendirmek mükemmel bir anlam ifade eder.

Orijinal nedeni bilmek istiyorsanız, eski Python posta listelerinde dolaşmanız veya orada olan birine (örn. Guido) sormanız gerekecek, ancak gerçekten sonra haklı çıkarmak için yeterince kolay:

Diğer dillerde olduğu kadar basit artış ve azalmaya gerek yoktur. for(int i = 0; i < 10; ++i)Python'daki gibi şeyleri çok sık yazmazsınız; bunun yerine böyle şeyler yaparsınız for i in range(0, 10).

Neredeyse sık ihtiyaç duyulmadığından, ona kendi özel sözdizimini vermek için çok daha az neden vardır; Artırmanız gerektiğinde +=, genellikle iyidir.

Bu mantıklı olup olmadığına ya da yapıp yapamayacağına karar vermez - yapar ve yapabilir. Bu, yararın dilin temel sözdizimine eklemeye değip değmeyeceği sorusudur. Unutmayın, bu dört operatördür - postinc, postdec, preinc, predec ve bunların her birinin kendi sınıf aşırı yüklerine sahip olması gerekir; hepsinin belirtilmesi ve test edilmesi gerekir; dile opcode ekler (daha büyük ve dolayısıyla daha yavaş bir VM motoru anlamına gelir); mantıksal artışı destekleyen her sınıf (üst üste bunları uygulamak gerekir +=ve -=).

Tüm bunlar gereksiz +=ve -=net bir kayıp olacak.


98
Düzenli olarak + = / - = ile yapılmayan dizi [i ++] gibi bir şey kullanmak genellikle yararlıdır.
Turner Hayes

102
@thayes: Bu Python'da yaygın bir örüntü değil.
Glenn Maynard

9
@thayes Bu bir döngü içinde olacağından, idoğrudan döngüye girebilirsiniz - eğer gerçekten ihtiyacınız varsa ve sadece kullanamazsanızarray.append()
Tobias Kienzler

31
Daha büyük endişenin okunabilirlik ve öngörülebilirlik olduğunu görüyorum. Geri benim C günlerde, ben fazla arasındaki farkla ilgili yanlış anlamalardan kaynaklanan yeterli hata gördüm i++ve ++i...
Charles Duffy

5
Gerçeği gerekçelendirmeye ek olarak: üzerinde çalıştığım bir projede, (hayatında herkesin yapması gerekenden daha fazla), sorunlardan muzdarip ++ve --tanımlanmamış veya belirtilmemiş sonuçlarla kullanılan adil bir miktarda C ++ kodu ile karşılaştım davranışı. Karmaşık, doğru şekilde ayrıştırılması zor kod yazmayı mümkün kılar.
Brian Vandenberg

84

Yazdığım bu orijinal cevap, bilgisayar folklorundan bir efsanedir : Dennis Ritchie tarafından editörlerin mektuplarına not edildiği gibi "tarihsel olarak imkansız" olarak atıldı ACM'nin İletişim atıldı Temmuz 2012 doi: 10.1145 / 2209249.2209251


C arttırma / azaltma operatörleri, C derleyicisinin çok akıllı olmadığı bir zamanda icat edildi ve yazarlar, bir derleyici için bir avuç döngü kaydeden bir makine dili operatörünün kullanılması gerektiği doğrudan niyetini belirtmek istediler. yapabilir

load memory
load 1
add
store memory

onun yerine

inc memory 

ve PDP-11 aşağıdakilere karşılık gelen "oto-artış" ve "oto-artış ertelenmiş" talimatları bile destekledi *++p*p++ , sırasıyla ve 'ye . Çok meraklıysanız kılavuzun 5.3 bölümüne bakın .

Derleyiciler, C sözdiziminde bulunan üst düzey optimizasyon hilelerini ele alacak kadar akıllı olduklarından, şimdi sadece sözdizimsel bir kolaylık.

Python'un, montajcıya niyetleri iletmek için hileleri yoktur çünkü bir tane kullanmaz.


4
Javascript'te ++ vardır. Bunun "montajcıya niyetleri iletmenin bir hilesi" olduğunu düşünmüyorum. Ayrıca, Python'un bayt kodu var. Bence sebebi başka bir şey.
Nathan Davis

13
Bu "derleyiciye ipuçları sağlamak" işi gerçekten bir efsanedir. Açıkçası, bu herhangi bir dile aptalca bir ek ve aşağıdaki iki ilkeyi ihlal ediyor: 1. Bilgisayarın okuması için kod yazmıyorsunuz, başka bir mühendisin okuması için kod yazıyorsunuz. Ve 2. Yetkili bir mühendisin okuması için kod yazmazsınız, yetkili bir mühendisin sabah 3'te tükendiğinde ve kafeine atlanırken okuması için kod yazarsınız.

3
@ tgm1024 Adil olmak gerekirse, saniyede 10-30 karakter, yarı çift yönlü teletype kodlarken, gelecek haftadan önce girebilmeniz için kod yazarsınız.
msw

4
@ tgm1024 Unix ve C, PDP-11'lerde kullanıcı iletişimi için inanılmaz derecede yavaş teletipler kullanan ilk geliştirmelerinin çoğunu gördüler. O ölü hakkını iken bugün o zamanlar makine için kodlama çoğunlukla aptal, o darboğaz oldu İnsan / Makine arabirimi oldu. Hiç gerekmediyse yavaş çalıştığını hayal etmek zor.
msw

65

Her zaman python zen bu çizgi ile ilgili olduğunu varsaydı:

Bunu yapmanın tek ve tercihen tek bir yolu olmalı.

x ++ ve x + = 1 tam olarak aynı şeyi yapar, bu yüzden ikisine birden sahip olmak için bir neden yoktur.


10
one--sıfır mı?
Andre Holzner

25
one--cümlede birdir, ama hemen sonra sıfırdır. Dolayısıyla bu 'koan', arttırma / azaltma operatörlerinin açık olmadığını da ima ediyor.
Victor K

14
@EralpB + = silerseniz, o zaman x + = 10 gibi şeyler yapamazsınız. + = Daha genel bir ++ örneğidir
Rory

8
Ayrıca: "Açık, örtük olmaktan iyidir".
Ber

2
Kesinlikle aynı değil, çünkü x + = 1 bir ifade DEĞİLDİR - bu bir deyimdir - ve hiçbir şeyi değerlendirmez. Gibi şeyler yapamazsınız: 'row [col ++] = a; satır [col ++] = b '. C ++ 'ın sahip olduğu öncesi ve sonrası şeyler bahsetmiyorum.
Uri

38

Tabii ki, "Guido bu şekilde karar verdi" diyebiliriz, ama bence soru gerçekten bu kararın nedenleri hakkında. Bence birkaç sebep var:

  • İyi uygulama olmayan ifadeleri ve ifadeleri bir araya getirir. Bkz. Http://norvig.com/python-iaq.html
  • Genellikle insanları daha az okunabilir kod yazmaya teşvik eder
  • Daha önce de belirtildiği gibi, Python'da gereksiz olan dil uygulamasında ekstra karmaşıklık

12
Memnuniyetle nihayet ifade ve ifade yönü bahsetti. C'de atama bir ifadedir ve bu nedenle ++ operatörüdür. Python ataması böylece, bir ifadedir eğer bu bir ++ vardı, büyük olasılıkla çok (ve hatta daha az yararlı veya gerekli), bir atama deyimi olması gerekir.
martineau

Kabul edildi - eğer ifadeler olsaydı, en azından post ve pre-operatörler arasındaki fark hakkında konuşmak kesinlikle anlamsız olurdu.
Crowman

17

Çünkü Python'da tamsayılar değiştirilemez (int's + = aslında farklı bir nesne döndürür).

Ayrıca, ++ / ile - arttırma / azaltma öncesi ile ilgili endişelenmeniz gerekir ve yazmak için yalnızca bir tuşa daha basın x+=1. Başka bir deyişle, çok az kazanç pahasına olası karışıklığı önler.


ints C de değişmezdir. Bunu, kodu oluşturmak için C derleyicisi elde etmeye çalışmak düşünmüyorsan 42++... böyle bir şey (bir hazır sabiti değiştirme) oldu Gelecekteki tüm kullanımlarını: Bazı eski Fortran derleyici mümkün aslında (ya da okudum bu yüzden) o program çalıştırmasındaki bu değişmez değerin gerçekten farklı bir değeri olacaktır. Mutlu hata ayıklama!
Lutz Prechelt

10
Sağ. 42 değişmez bir sabittir . Sabitler değişmezdir (veya en azından olmalıdır ). Bu C'nin intgenel olarak değişmez olduğu anlamına gelmez . Bir intC basitçe belleğinde yer belirler. Ve oradaki bitler çok değişkendir. Örneğin, bir referans oluşturabilir intve bu referansın referansını değiştirebilirsiniz. Bu değişiklik into yere yapılan tüm referanslarda (orijinal değişken dahil) görülebilir . Aynı şey bir Python tamsayı nesnesi için de geçerli değildir.
Nathan Davis

x + = 1, sonunda inc olur. Python, bir değişkene 1 eklemek için bir işlev çağrısı yürütür; dokunaklı.
PalaDolphin

12

Netlik!

Python açıklık konusunda çok fazladır ve hiçbir programcı --abu yapıya sahip bir dil öğrenmedikçe anlamını doğru bir şekilde tahmin edemez.

Python ayrıca hataları davet eden yapılardan kaçınmakla da ilgilidir ve ++operatörlerin zengin kusur kaynakları olduğu bilinmektedir. Bu iki neden, bu operatörlerin Python'da olmaması için yeterlidir.

Python'un bir tür başlangıç ​​/ bitiş basamaklama veya zorunlu son işaretleme gibi sözdizimsel araçlardan ziyade blokları işaretlemek için girintiyi kullandığı kararı büyük ölçüde aynı hususlara dayanır.

Örnek olarak, 2005'te Python'a bir koşullu operatör (C: cond ? resultif : resultelsecinsinden) getirme konusundaki tartışmaya bir göz atın . En azından ilk mesajı ve karar mesaj bunun tartışma (daha önce aynı konuda birkaç öncüleri vardı).

Diğer bilgiler: Burada sıkça bahsedilen PEP, "Python Genişletme Teklifi" PEP 308'dir . LC, liste anlama anlamına gelir , GE jeneratör ifadesi anlamına gelir (ve eğer bunlar sizi karıştırırsa endişelenmeyin, Python'un birkaç karmaşık noktasından hiçbiri değildir).


10

Python'un neden ++operatör olmadığına dair anlayışım şu: Bunu python'a yazdığınızda a=b=c=1, aynı nesneyi işaret eden üç değişken (etiket) elde edersiniz (bu değer 1'dir). Bir nesne bellek adresi döndürecek id işlevini kullanarak bunu doğrulayabilirsiniz:

In [19]: id(a)
Out[19]: 34019256

In [20]: id(b)
Out[20]: 34019256

In [21]: id(c)
Out[21]: 34019256

Her üç değişken (etiket) de aynı nesneyi gösterir. Şimdi değişkenlerden birini artırın ve bellek adreslerini nasıl etkilediğini görün:

In [22] a = a + 1

In [23]: id(a)
Out[23]: 34019232

In [24]: id(b)
Out[24]: 34019256

In [25]: id(c)
Out[25]: 34019256

Bu değişkenin aartık başka bir nesneyi değişken bve olarak gösterdiğini görebilirsiniz c. Çünkü kullandığınız a = a + 1açıkça belli. Başka bir deyişle, etikete tamamen başka bir nesne atarsınız a. Yazabileceğinizi düşünün ki a++, değişken ayeni nesneye atamadığınızı, ancak daha eski olanı artırdığınızı düşündürür. Bütün bunlar karışıklığı en aza indirmek için IMHO'dur. Daha iyi anlamak için python değişkenlerinin nasıl çalıştığını görün:

Python'da, bir işlev neden bazı argümanları arayan tarafından algılanan şekilde değiştirebilir, ancak diğerleri değiştiremez?

Python değere göre çağrı mı, yoksa referans numarası mı? Ne.

Python değere veya referansa göre geçiyor mu?

Python referansla mı yoksa değerle mi?

Python: Bir değişkeni referans olarak nasıl iletirim?

Python değişkenlerini ve Bellek Yönetimini Anlama

Python'da değere göre by-pass davranışını taklit etme

Python fonksiyonları referans ile çağrı

Pythonista Gibi Kod: Deyimsel Python


9

Sadece bu şekilde tasarlandı. Artış ve eksiltme operatörleri sadece kısayollardır x = x + 1. Python, tipik olarak, bir işlemi gerçekleştirmenin alternatif yollarının sayısını azaltan bir tasarım stratejisi benimsemiştir. Artırılmış atama , Python'daki operatörleri artırmaya / azaltmaya en yakın şeydir ve Python 2.0'a kadar eklenmediler.


3
Evet dostum, gibi sen yerini alabilir return a[i++]ile return a[i=i+1].
Luís de Sousa

7

Python için çok yeniyim ama bunun nedeni, dilin değişebilir ve değişmez nesneleri arasındaki vurgudan kaynaklandığından şüpheleniyorum. Şimdi, x ++ 'ın x = x + 1 olarak kolayca yorumlanabileceğini biliyorum, ama değişmez olabilecek bir nesneyi yerinde artırıyormuşsunuz gibi görünüyor .

Sadece tahminim / duygu / önsezim.


Bu açıdan bakıldığında, x++daha yakın olduğu x += 1için daha x = x + 1bu iki değişken nesneler üzerinde de bir fark yaratmak.
glglgl

4

İlk olarak, Python sadece dolaylı olarak C'den etkilenir; o ağır etkilenir ABC , görünüşe göre bu operatörler yok o Python Ya onları bulmak için değil, herhangi büyük bir sürpriz olmamalı bu yüzden.

İkincisi, diğerlerinin söylediği gibi, artış ve azalış zaten +=ve -=zaten tarafından desteklenmektedir .

Üçüncü olarak, bir ++ve --operatör kümesi için tam destek genellikle bunların önek ve son düzeltme sürümlerinin desteklenmesini içerir. C ve C ++ 'da bu, (bana göre) Python'un kucakladığı basitlik ve dürüstlük ruhuna aykırı görünen her türlü "güzel" yapıya yol açabilir.

Örneğin, C ifadesi while(*t++ = *s++);deneyimli bir programcı için basit ve zarif görünse de, onu öğrenen biri için bu basit bir şeydir. Önek ve düzeltme sonrası artışların ve düşüşlerin bir karışımını atın ve birçok profesyonel bile biraz durup düşünmek zorunda kalacak.


3

Ben inanıyorum Python inanç "açık dolaylı daha iyidir" kaynaklanıyor.


Python'a açıkça "begin" ve "end" ifadelerini yazmıyorsunuz, değil mi? İfadeyi kabul etsem de, bunun bir sınırı olduğunu düşünüyorum. Bu sınırlar üzerinde tartışabilirken, hepimizin hemfikir olabileceğini düşünüyorum, geçilmesi pratik olmayan bir çizgi var. Ve bu karar hakkında çok fazla fikir ve gerekçe olduğu için, bunun net bir seçim olduğunu düşünmüyorum. En azından açıkça belirtildiği bir kaynak bulamıyorum
Hasan Ammori

3

Bunun nedeni @GlennMaynard'ın konuya diğer dillerle karşılaştırıldığında bakması olabilir , ancak Python'da işleri python yolu ile yaparsınız. Bu 'neden' sorusu değil. Orada ve aynı etkiye sahip şeyleri yapabilirsiniz x+=. In Python Zen , verilir: "Yalnızca bir sorunu çözmek için bir yol bulunmalıdır." Birden fazla seçenek sanatta mükemmeldir (ifade özgürlüğü) ancak mühendislikte berbattır.


2

++Operatörlerin sınıf yan etkileri ile ifadelerdir. Bu genellikle Python'da bulunmayan bir şeydir.

Aynı nedenden ötürü bir ödev Python'da bir ifade değildir, böylece ortak if (a = f(...)) { /* using a here */ }deyimi önler .

Son olarak, operatörün Pythons referans semantiği ile çok tutarlı olmadığından şüpheleniyorum. Unutmayın, Python'un C / C ++ 'dan bilinen anlambilimiyle değişkenleri (veya işaretçileri) yoktur.


1
hiçbir şey bir test / ifade / liste kavramada yan etkisi olan bir işlevi çağırmayı engellemez: f(a)burada abir liste, değişmez bir nesne.
Jean-François Fabre

1

Belki de daha iyi bir soru, bu operatörlerin neden C'de bulunduğunu sormak olabilir. K&R, arttırma ve azaltma operatörlerini 'olağandışı' olarak adlandırır (Bölüm 2.8 sayfa 46). Giriş onlara 'daha özlü ve genellikle daha verimli' diyor. Bu operasyonların her zaman işaretçi manipülasyonunda ortaya çıkmasının da tanıtımlarında bir rol oynadığından şüpheleniyorum. Python'da muhtemelen artışları optimize etmeye çalışmanın mantıklı olmadığına karar verildi (aslında sadece C'de bir test yaptım ve gcc tarafından oluşturulan montajın her iki durumda da incl yerine addl kullandığı görülüyor) ve yok işaretçi aritmetiği; yani bunu yapmanın sadece bir yolu daha olurdu ve Python'un bunu sevdiğini biliyoruz.


1

anladığım kadarıyla bellekteki değerin değiştiğini düşünmeyeceksiniz. c ++ ile yaptığınız zaman bellekte x değeri değişir. ancak python'da tüm sayılar değişmez olduğundan x'in işaret ettiği adres x + 1 değil. x ++ yazdığınızda, x değişiminin gerçekte ne olduğunu, x referansının x + 1'in depolandığı bir konum olarak değiştirildiğini veya doe yoksa bu konumu yeniden oluşturduğunu düşünürsünüz.


1
Peki bunu ++farklı kılan += 1nedir?
Ber

1

Bu sayfada zaten iyi yanıtları tamamlamak için:

Diyelim ki bunu yapmaya karar veriyoruz ++i, tekli + ve - operatörlerini kıracak önek ( ).

Bugün, önekleme ++veya --hiçbir şey yapmaz, çünkü tekli artı operatöre iki kez (hiçbir şey yapmaz) veya tekli eksi iki kez (iki kez: kendini iptal eder)

>>> i=12
>>> ++i
12
>>> --i
12

Böylece bu potansiyel olarak bu mantığı kırabilir.


1

Diğer cevaplar, yineleyiciler için neden gerekli olmadığını açıkladı, ancak bazen bir değişkeni satır içi artırmak için atarken faydalıdır, tuples ve çoklu atama kullanarak aynı efekti elde edebilirsiniz:

b = ++a dönüşür:

a,b = (a+1,)*2

ve b = a++olur:

a,b = a+1, a

Python 3.8 atama tanıtır :=bize ulaşmak için izin operatörü foo(++a)ile

foo(a:=a+1)

foo(a++) yine de zor.


2
: = atama utanç verici
nehem

0

Bunun nesnelerin değişebilirliği ve değişmezliği kavramlarıyla ilgili olduğunu düşünüyorum. 2,3,4,5 python ile değişmez. Aşağıdaki resme bakın. 2, bu python işlemine kadar kimliği sabitledi.

Sabitlerin ve değişkenlerin kimliği

x ++ esasen C gibi bir yerinde artış anlamına gelir. C'de x ++ yerinde artışlar gerçekleştirir. Bu nedenle, x = 3 ve x ++, bellekte 3'ün var olacağı python'un aksine, bellekte 3'ü 4'e yükseltir.

Böylece python'da, hafızadaki bir değeri yeniden oluşturmanız gerekmez. Bu performans optimizasyonlarına yol açabilir.

Bu önsezi tabanlı bir cevap.


0

Bu eski bir iş parçacığı olduğunu biliyorum, ancak ++ i için en yaygın kullanım durumu, sağlanan dizinler olmadığında el ile dizin oluşturma olan bu kapsam dahil değildir. Bu durum python'un enumerate ()

Örnek: Herhangi bir dilde, bir kümeyi yinelemek için foreach gibi bir yapı kullandığınızda - örnek uğruna bunun sırasız bir küme olduğunu bile söyleyebiliriz ve her şeyin onları ayırt etmesi için benzersiz bir dizine ihtiyacınız vardır, diyelim

i = 0
stuff = {'a': 'b', 'c': 'd', 'e': 'f'}
uniquestuff = {}
for key, val in stuff.items() :
  uniquestuff[key] = '{0}{1}'.format(val, i)
  i += 1

Bu gibi durumlarda, python numaralandırma yöntemi sağlar, örn.

for i, (key, val) in enumerate(stuff.items()) :
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.