Python'un birçok dize biçimlendirme yöntemi - eskileri (mi kullanılacak) kullanımdan kaldırılacak mı?


107

Python'da bir dizeyi biçimlendirmenin en az altı yolu vardır:

In [1]: world = "Earth"

# method 1a
In [2]: "Hello, %s" % world
Out[2]: 'Hello, Earth'

# method 1b
In [3]: "Hello, %(planet)s" % {"planet": world}
Out[3]: 'Hello, Earth'

# method 2a
In [4]: "Hello, {0}".format(world)
Out[4]: 'Hello, Earth'

# method 2b
In [5]: "Hello, {planet}".format(planet=world)
Out[5]: 'Hello, Earth'

# method 2c
In [6]: f"Hello, {world}"
Out[6]: 'Hello, Earth'

In [7]: from string import Template

# method 3
In [8]: Template("Hello, $planet").substitute(planet=world)
Out[8]: 'Hello, Earth'

Farklı yöntemlerin kısa bir geçmişi:

  • printf-stili biçimlendirme Pythons'un bebeklik döneminden beri var
  • TemplateSınıf Python 2.4 kullanılmaya başlandı
  • formatYöntem Python 2.6 tanıtıldı
  • f-strings Python 3.6'da tanıtıldı

Sorularım:

  • printf-Style biçimlendirme kullanımdan kaldırıldı mı yoksa kullanımdan kaldırılacak mı?
  • Yılında Template classolduğu substituteyöntem eskimiştir veya kullanım dışı olacak? (Anladığım safe_substitutekadarıyla benzersiz yetenekler sunduğundan bahsetmiyorum )

Benzer sorular ve neden bunların yinelenmediğini düşünüyorum:

  • Python dizesi biçimlendirmesi:% ve .format - yalnızca 1. ve 2. yöntemleri ele alır ve hangisinin daha iyi olduğunu sorar; Sorum açıkça Python Zen ışığında kullanımdan kaldırma ile ilgili

  • Dize biçimlendirme seçenekleri: artılar ve eksiler - yalnızca soruda 1a ve 1b, yanıtta 1 ve 2 yöntemlerini ve ayrıca kullanımdan kaldırmayla ilgili hiçbir şeyi ele almaz

  • gelişmiş dize biçimlendirmesine karşı şablon dizeleri - çoğunlukla yöntem 1 ve 3 hakkındadır ve kullanımdan kaldırmaya değinmez

  • Dize biçimlendirme ifadeleri (Python) - yanıt , orijinal '%' yaklaşımının kullanımdan kaldırılmasının planlandığından bahsediyor . Ama arasındaki fark nedir kaldırılacaktır planlanan , Kullanımdan kaldırmayı bekleyen ve fiili Kullanımdan kaldırmayı ? Ve printf-style yöntemi a bile yükseltmiyor PendingDeprecationWarning, bu yüzden bu gerçekten kullanımdan kaldırılacak mı? Bu gönderi de oldukça eski olduğu için bilgiler güncel olmayabilir.

Ayrıca bakınız


1
Dersi unuttuğunuzu belirtmeme gerek var Formattermı?
Martijn Pieters

Yanıtlar:


15

Dokümanlarda .formatf-dizelerinin dizelerden daha üstün olduğuna dair çeşitli göstergeler olsa da %, ikincisini reddetmek için hayatta kalan bir plan yok.

İşlemeleri durumunda Sorun # 14123: Açıkça eski tarz% dize uyarısı var biçimlendirme ama yakın zamanda uzağa gitmiyor söz. , sorundan esinlenildi Printf -tarzı biçimlendirmeyi kullanımdan kaldırmaya yönelik mevcut bir plan olmadığını% belirtin , -formatting ile ilgili dokümanlar şu ifadeyi içerecek şekilde düzenlendi:

Yeni dize biçimlendirme sözdizimi daha esnek olduğundan ve tuple ve sözlükleri doğal olarak işlediğinden, yeni kod için önerilir. Ancak, printf stili biçimlendirmeyi kullanımdan kaldırmaya yönelik mevcut bir plan yoktur .

(Vurgu benim.)

Bu ifade daha sonra commit Close # 4966'da kaldırıldı : modern Python'un durumunu daha iyi açıklamak için sekans belgelerini yenileyin . Bu, %biçimlendirmeyi reddetme planının tekrar kartlarda olduğuna dair bir işaret gibi görünebilir ... ancak hata izleyiciye dalmak, amacın tam tersi olduğunu ortaya çıkarır. Hata izleyicide, commit'in yazarı değişikliği şu şekilde karakterize eder :

  • printf tarzı biçimlendirme ile str.format yöntemi arasındaki ilişkiyi tanımlayan düzyazı değiştirdi (kasıtlı olarak, ilkinin gerçek bir yok olma tehlikesi olduğu imasını ortadan kaldırır - onu öldürmeyi ciddi bir şekilde düşünmek bizim için pratik değildir)

Diğer bir deyişle, biz iki ardışık değişiklikler yaşadım %amaçlanan -Biçimlendirme docs vurgulamak açıkça bunun olacağını değil kaldırılan şöyle dursun, kaldırılabilir. Dokümanlar, farklı dize biçimlendirme türlerinin göreli yararları konusunda %görüş sahibi olmaya devam ediyor , ancak aynı zamanda -formatlamanın kullanımdan kaldırılmayacağı veya kaldırılmayacağı da açık .

Dahası , Mart 2017'de bu paragrafta yapılan en son değişiklik , onu bundan değiştirdi ...

Burada açıklanan biçimlendirme işlemleri, bir dizi yaygın hataya yol açan çeşitli tuhaflıklar sergiler (örneğin, başlıkların ve sözlüklerin doğru görüntülenmemesi). Daha yeni biçimlendirilmiş dize değişmezlerini veya str.formatarabirimi kullanmak, bu hataları önlemeye yardımcı olur. Bu alternatifler ayrıca metni biçimlendirmek için daha güçlü, esnek ve genişletilebilir yaklaşımlar sağlar.

... buna:

Burada açıklanan biçimlendirme işlemleri, bir dizi yaygın hataya yol açan çeşitli tuhaflıklar sergiler (örneğin, dizilerin ve sözlüklerin doğru görüntülenmemesi). Daha yeni biçimlendirilmiş dize değişmezlerini, str.formatarabirimi veya şablon dizelerini kullanmak bu hataları önlemeye yardımcı olabilir. Bu alternatiflerin her biri kendi değiş tokuşlarını ve basitlik, esneklik ve / veya genişletilebilirlik avantajlarını sağlar.

"Kaçınmaya yardımcı olur" dan "kaçınmaya yardımcı olabilir" şeklindeki değişikliğe ve .formather bir stilin nasıl "kendi değiş tokuşlarını ve avantajlarını sağladığına" ilişkin net öneri ve f-dizgilerinin nasıl kabarık, belirsiz düzyazı ile değiştirildiğine dikkat edin . Yani, artık kartlarda resmi bir kullanımdan kaldırma değil, aynı zamanda mevcut dokümanlar, %biçimlendirmenin diğer yaklaşımlara göre en azından bazı "faydaları" olduğunu açıkça kabul ediyor .

Tüm %bunlardan, biçimlendirmeyi kullanımdan kaldırma veya kaldırma hareketinin yalnızca sarsılmadığını, aynı zamanda tamamen ve kalıcı olarak yenilgiye uğradığını anladım .


2
Kabarık dil değişikliği, Mercurial'in kullanımını ortadan kaldırmak için çok büyük bir kod tabanıyla geride bıraktığını görmek istemeyen Mercurial bakımcılarını (diğerlerinin yanı sıra) yatıştırmak için eklendi %. Artık 'büyük ölçekli kod modları yok' politikası hurdaya çıkarıldığına göre, itirazları da kayboluyor. Uzun vadede, bir % noktada printf sözdizimi için hiçbir fayda kalmadan her iki formun da korunması yine de kaldırılacaktır. Henüz ne zaman olduğunu bilmiyoruz ve bu yüzden dil tonunu azaltmaya değerdi.
Martijn Pieters

@MartijnPieters İlginç. Eksik olduğum bu karar hakkında epey bilgin var gibi görünüyor. Değeri ne olursa olsun, sizden bu noktaları özetleyen iyi referanslı bir cevabın (ya yeni bir cevap ya da mevcut cevabınızda bir düzenleme olarak) değerli olacağını düşünüyorum.
Mark Amery

58

Yeni .format()yöntemin eski %biçimlendirme sözdiziminin yerini alması amaçlanmıştır . İkincisi, de-vurguladı (ancak resmen onaylanmamış değil edilmiştir henüz ). Yöntem dokümantasyonu şunları belirtir:

Dize biçimlendirme yöntemi Python 3 yeni bir standarttır ve tercih edilmelidir için %tarif edilen biçimlendirme dize biçimlendirme işlemleri , yeni kodda olabilir.

(Vurgu benim).

Geriye dönük uyumluluğu korumak ve geçişi kolaylaştırmak için eski format şimdilik yerinde bırakıldı . Orijinal PEP 3101 teklifinden :

Geriye Dönük Uyumluluk

Mevcut mekanizmaları yerinde bırakarak geriye dönük uyumluluk korunabilir. Yeni sistem, mevcut dizgi biçimlendirme tekniklerinin yöntem adlarından hiçbiriyle çakışmaz, bu nedenle her iki sistem de eski sistemi kullanımdan kaldırma zamanı gelene kadar birlikte var olabilir.

Eski sistemi kullanımdan kaldırma zamanı gelene kadar not edin ; kullanımdan kaldırılmadı, ancak her yeni kod yazdığınızda yeni sistem kullanılacak .

Yeni sistemin avantajı , eski formatlayıcının başlıkla ve sözlük yaklaşımını birleştirebilmenizdir% :

"{greeting}, {0}".format(world, greeting='Hello')

ve object.__format__()tek tek değerlerin biçimlendirmesini işlemek için kullanılan kancayla genişletilebilir .

Eski sistemin %ve Templatesınıfın sahip olduğunu unutmayın; burada ikincisi, davranışını ekleyen veya değiştiren alt sınıflar oluşturmanıza izin verir. Yeni stil sistemi, aynı boşluğu dolduracak Formattersınıfa sahiptir .

Python 3, kullanımdan kaldırmadan daha da uzaklaştı, bunun yerine printf-style Dize Biçimlendirme bölümünde sizi uyarıyor :

Not : Burada açıklanan biçimlendirme işlemleri, bir dizi yaygın hataya yol açan çeşitli tuhaflıklar sergiler (örneğin, başlıkların ve sözlüklerin doğru görüntülenmemesi). Daha yeni biçimlendirilmiş dize değişmezlerini veya str.format()arabirimi kullanmak, bu hataları önlemeye yardımcı olur. Bu alternatifler ayrıca metni biçimlendirmek için daha güçlü, esnek ve genişletilebilir yaklaşımlar sağlar.

Python 3.6 da eklenen biçimlendirilmiş dize hazır , hangi sıralı ifadeleri içine biçim dizeleri. Bunlar, enterpolasyonlu değerlere sahip dizeler oluşturmanın en hızlı yöntemidir ve str.format()bir değişmezi kullanabileceğiniz her yer yerine kullanılmalıdır .


4
Ve Formattersizinle datetimenesnelerin kullandığı gibi özel formatlar oluşturabilirsiniz . Ayrıca, .formatbir işlev olduğu için, çağrılabilir tembel biçimlendirmeyi daha doğrudan oluşturmak için kullanabilirsiniz: örneğin,fmt = '{} - {}'.format; fmt(a, b)
Jon Clements

Ben nasıl görmüyorum Templateilişkilidir %veya eski sistem . Özellikle bağladığınız KEP , bu teklif arasında bazı örtüşmeler varken, string.Templateher birinin ayrı bir ihtiyaca hizmet ettiği ve birinin diğerini ortadan kaldırmadığı hissedilir. Cevabınızda Template, eski sistemin bir parçası olan biçimlendirmenin de kullanımdan kaldırıldığı konusunda kafa karışıklığı olabilir .
Bakuriu

@Bakuriu: Doğru, sanırım o kısmı kaçırdım; ama bence Formattersınıfla aynı ihtiyaçları karşılayabilir string.Template().
Martijn Pieters

1
[...]should be preferred to the % formatting[...]bu bölüm belgelerden çıkarılmıştır. docs.python.org/3/library/stdtypes.html#str.format
AXO

Bu cevabın şu anda yanıltıcı olduğunu düşünüyorum; alıntılanan ilk pasaj Python 3 belgelerinden kaldırıldı ve bana göre bir kullanımdan kaldırma işleminin gerçekleşmesi için hiçbir niyet kalmadığı oldukça açık. Bu cevabın hala tarihsel bir değeri var, ancak hala kartlarda bir kullanımdan kaldırmanın olduğu şeklindeki herhangi bir öneriden kaçınmak için ifadelerde ince ayar yapmaya ve cevabın ilk yarısının çoğunu geçmiş zamanda olacak şekilde düzenlemeye meyilliyim. Eğer itiraz etmezseniz bir noktada kendim yapacağım, ancak önce size bu tür değişiklikleri kendi başınıza yapma şansı vermek için yorum yapmam gerektiğini düşündüm.
Mark Amery

45

%Dize biçimlendirmesi için operatör kullanım dışı değildir ve kaldırılması gitmiyor - diğer cevaplar rağmen.
Konu Python geliştirme listesinde her gündeme getirildiğinde, hangisinin daha iyi olduğu konusunda güçlü bir tartışma vardır, ancak klasik yolu kaldırıp kaldırmayacağına dair hiçbir tartışma yoktur - kalacaktır. PEP 3101'de belirtilmesine rağmen, Python 3.1 geldi ve gitti ve %biçimlendirme hala var.

Klasik tarzı korumaya yönelik ifadeler açıktır: basittir, hızlıdır, kısa şeyler için yapmak hızlıdır. .formatYöntemi kullanmak her zaman daha okunaklı değildir - ve neredeyse hiç kimse - çekirdek geliştiriciler arasında bile .format, referansa bakmak zorunda kalmadan tarafından sağlanan tam sözdizimini kullanabilir . 2009'da bile, böyle mesajlar vardı: http: // mail. python.org/pipermail/python-dev/2009-October/092529.html - konu o zamandan beri listelerde neredeyse hiç görünmüyordu .

2016 güncellemesi

Mevcut Python geliştirme sürümünde (Python 3.6 olacak), PEP-0498'de açıklanan üçüncü bir dize enterpolasyonu yöntemi vardır . Bu yeni bir alıntı öneki tanımlar f""(akımınınkine katkı u"", b""ve r"").

Bir dizenin ön eki f, çalışma zamanında dize nesnesinde bir yöntemi çağırır ve bu yöntem, geçerli kapsamdaki değişkenleri dizeye otomatik olarak enterpolasyon yapar:

>>> value = 80
>>> f'The value is {value}.'
'The value is 80.'

3
Türlerin kendilerininkini uygulamasına izin vermek çok daha hoş __format__. Örneğin, format(Decimal('0.1'), '.20f')vs '%.20f' % Decimal('0.1'). İkincisi, Ondalık değerini bir kayan noktaya zorlar.
Eryk Paz

2
NB. Eski tarzın her bakımdan daha iyi olduğunu tartışmadım - sadece daha kısa ve bazen daha okunaklı (ve bazen değil). Yeni yöntem kesinlikle çok daha esnektir.
jsbueno

fPython 3'te bir eşdeğeri var mı ?
Daniel

f-stringsYukarıda kullanıldığı gibi Python 3.6 olarak dilinde yeni bir özelliktir. Önceki sürümlerde mevcut değildir ve bunlar üzerinde bir Sözdizimi Hatası oluşturacaktır.
jsbueno

20

Guido'nun bu konudaki son pozisyonu burada belirtilmiş gibi görünüyor:

Python 3.0'daki Yenilikler

PEP 3101: Dize Biçimlendirmeye Yeni Bir Yaklaşım

Yerleşik dize biçimlendirme işlemleri için yeni bir sistem,% dize biçimlendirme operatörünün yerini alır. (Bununla birlikte,% operatörü hala desteklenmektedir; Python 3.1'de kullanımdan kaldırılacak ve daha sonra dilden kaldırılacaktır.) Kapsamın tamamı için PEP 3101'i okuyun.

Ve PEP3101'in kendisi de (30 Eylül 2011 Cuma) en son değiştirilmiş haldedir , yani sanırım bunun sonlarına doğru ilerleme yok.


18

Eski Python belgelerine ve PEP 3101'e bakıldığında,% operatörünün kullanımdan kaldırılacağına ve gelecekte dilden kaldırılacağına dair bir ifade vardı. Aşağıdaki açıklamada Python 3.0, 3.1 ve 3.2 için Python docs oldu:

Str.format () oldukça yeni olduğundan, birçok Python kodu hala% operatörünü kullanır. Ancak, bu eski biçimlendirme stili eninde sonunda dilden kaldırılacağından, genellikle str.format () kullanılmalıdır.

Eğer giderseniz aynı bölümde Python 3.3 ve 3.4 docs, sen deyimi kaldırıldığını göreceksiniz. Ayrıca dokümantasyonun başka hiçbir yerinde operatörün kullanımdan kaldırılacağını veya dilden çıkarılacağını belirten başka bir ifade bulamıyorum. PEP3101'in iki buçuk yıldan fazla bir süredir değiştirilmediğine dikkat etmek de önemlidir (Cum, 30 Eylül 2011).

Güncelleme

PEP461 Baytlara ve bytearray'e % biçimlendirme eklemek kabul edilir ve Python 3.5 veya 3.6'nın bir parçası olmalıdır. % Operatörünün hayatta ve tekmelediğinin başka bir işaretidir.

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.