“U” ve “r” string bayrakları tam olarak ne yapar ve ham string değişmezleri nelerdir?


652

Bu soruyu sorarken , ham teller hakkında fazla bir şey bilmediğimi fark ettim. Django antrenörü olduğunu iddia eden biri için bu berbat.

Bir kodlamanın ne olduğunu biliyorum ve u''Unicode'u aldığımdan beri tek başına ne yaptığını biliyorum .

  • Ama r''tam olarak ne yapar ? Ne tür bir dize ile sonuçlanır?

  • Ve her şeyden önce, halt ne yapar ur''?

  • Son olarak, bir Unicode dizesinden basit bir ham dizeye geri dönmenin güvenilir bir yolu var mı?

  • Ah, bu arada, sisteminiz ve metin düzenleyici karakter kümeniz UTF-8 olarak ayarlanmışsa, u''gerçekten bir şey yapar mı?

Yanıtlar:


683

Gerçekten herhangi bir "ham dize " yoktur; açılış dizgesinden önce bir ile işaretlenmiş dize değişmez değerleri olan ham dize değişmez değerleri vardır 'r'.

"Ham dize değişmez değeri", ters eğik çizginin \"yalnızca ters eğik çizgi" anlamına geldiği bir dizgi değişmezinin biraz farklı bir sözdizimidir. yeni satırları, sekmeleri, arka boşlukları, form beslemelerini vb. temsil etmek için "kaçış dizileri". Normal dizgi değişmezlerinde, bir kaçış dizisinin başlangıcı olarak alınmamak için her ters eğik çizginin iki katına çıkarılması gerekir.

Bu sözdizimi varyantı çoğunlukla düzenli ifade desenlerinin sözdizimi ters eğik çizgilerle ağır olduğu için (ancak asla sonunda değil, bu nedenle yukarıdaki "hariç" maddesi önemli değildir) ve her birini ikiye katlamaktan kaçındığınızda biraz daha iyi görünüyor - - bu kadar. Ayrıca yerel Windows dosya yollarını (diğer platformlarda olduğu gibi normal eğik çizgiler yerine ters eğik çizgilerle) ifade etmek için biraz popülerlik kazandı, ancak bu çok nadiren gerekli (normal eğik çizgiler çoğunlukla Windows'ta da iyi çalıştığı için) ve kusurlu ("hariç" cümlesi nedeniyle) ile elde edilmiş).

r'...'(Python 2. * olarak) bir bayt dize olan ur'...'bir Unicode dizesi (yine Python 2. *), ve alıntı diğer üç çeşit herhangi ayrıca dizeleri tam olarak aynı tip üretir (dolayısıyla örneğin r'...', r'''...''', r"...", r"""..."""hepsi bayt dizeleridir vb.).

" Geri dönerek " ne demek istediğinizden emin değilsiniz - özünde geri ve ileri yönler yoktur, çünkü ham dize türü yoktur , sadece normal dize nesnelerini, bayt veya unicode'u olabildiğince ifade etmek için sadece alternatif bir sözdizimi.

Ve evet, Python 2. * daki, u'...' olduğu gibi farklı ders her zaman '...'- Eski bir Unicode dize, ikincisi bir bayt dizisidir. Değişmezi kodlayan şey tam olarak dik bir konudur.

Örneğin, düşünün (Python 2.6):

>>> sys.getsizeof('ciao')
28
>>> sys.getsizeof(u'ciao')
34

Unicode nesnesi elbette daha fazla bellek alanı kaplıyor (çok kısa bir dize için çok küçük fark, tabii ki ;-).


6
"R" yi anlamak herhangi bir tür veya kodlama sorunu anlamına gelmez, çok daha basittir.
e-satis

23
\ U ru modunda bir unicode kaçış dizisi olduğundan ru "C: \ foo \ kararsız" ın başarısız olacağını unutmayın. r modunda \ u yok.
Curtis Yallop

26
Unutmayın uve rdeğişmeli değildir: ur'str'çalışır, ru'str'değil. (en azından win7'de ipython 2.7.2'de)
RafiK

7
Sadece rdizeleri test etti \ ve son karakter ise bir değişmez olarak alınmayacağını, bunun yerine kapanış teklifinden kaçarak, neden olduğunu fark ettim SyntaxError: EOL while scanning string literal. Bu yüzden \\ yine de \ ters eğik çizgi ile biten dizelerin son örneği için kullanılmalıdır .
Enteleform

1
python 3.x - sys.getsizeof('cioa') == sys.getsizeof(r'cioa') == sys.getsizeof(u'cioa')(UTF8 dili ile Ubuntu 16.04). Benzer şekilde type('cioa') == type(r'cioa') == type(u'cioa'),. ANCAK, ham dize enterpolasyonu bir fark yaratıyor, bu yüzdensys.getsizeof('\ncioa') == sys.getsizeof(u'\ncioa') != sys.getsizeof(r'\ncioa')
Darren Weber

177

Python'da iki tür dize vardır: geleneksel strtür ve daha yeni unicodetür. uÖnde olmayan bir dize değişmezi yazarsanız, str8 bit karakterleri depolayan eski türü ualırsınız ve önde ise unicodeherhangi bir Unicode karakterini saklayabilen daha yeni bir tür elde edersiniz .

rSadece dize yorumlanır nasıl değiştirir, hiç türünü değiştirmez. Olmadan r, ters eğik çizgiler kaçış karakteri olarak kabul edilir. İle r, ters eğik çizgiler değişmez olarak kabul edilir. Her iki durumda da, tür aynıdır.

ur Elbette, ters eğik çizgilerin kaçış kodlarının bir parçası değil, gerçek ters eğik çizgi olduğu bir Unicode dizesidir.

Bu str()işlevi kullanarak bir Unicode dizesini eski bir dizeye dönüştürmeyi deneyebilirsiniz , ancak eski dizede temsil edilemeyen herhangi bir unicode karakter varsa, bir istisna alırsınız. İsterseniz önce bunları soru işaretleriyle değiştirebilirsiniz, ancak bu elbette bu karakterlerin okunamaz olmasına neden olacaktır. strUnicode karakterleri doğru şekilde işlemek istiyorsanız, bu türün kullanılması önerilmez .


Teşekkürler, kabul etti. Dediğim gibi, unicode'un ne olduğunu biliyorum, "r" nin ne anlama geldiğini ve "u" ve "r" nin birleşiminin ne olacağını bilmiyordum. Daha iyisini biliyorum, şerefe.
e-satis

6
Ters eğik çizgiler ham dize değişmezlerinde değişmez olarak ele alınmaz, bu yüzden r"\"bir sözdizimi hatasıdır.

4
Sadece Python 2 için geçerlidir.
PaulMcG

60

'raw string' , göründüğü gibi saklandığı anlamına gelir. Örneğin, '\'sadece bir olan ters eğik çizgi yerine ait kaçması .


3
... dizenin son karakteri olmadıkça, bu durumda kapanış alıntısından kaçar.
jez

36

Bir "u" öneki, değerin unicodeyerine türü olduğunu belirtir str.

Ham dize değişmezleri, "r" önekiyle, içlerindeki herhangi bir kaçış dizisinden kaçarlar, bu yüzden len(r"\n")2'dir. Kaçış dizilerinden kaçtıkları için, bir dize değişmezini tek bir ters eğik çizgi ile sonlandıramazsınız: bu geçerli bir kaçış dizisi değil (ör. r"\").

"Raw" türün bir parçası değildir, değeri temsil etmenin yalnızca bir yoludur. Örneğin, "\\n"ve r"\n"sadece, eş değerleri 32, 0x20ve 0b100000aynıdır.

Unicode ham dize değişmezlerine sahip olabilirsiniz:

>>> u = ur"\n"
>>> print type(u), len(u)
<type 'unicode'> 2

Kaynak dosya kodlaması, kaynak dosyanın nasıl yorumlanacağını belirler, aksi halde ifadeleri veya türleri etkilemez. Ancak, ASCII dışında bir kodlamanın anlamını değiştireceği koddan kaçınılması önerilir :

ASCII (veya Python 3.0 için UTF-8) kullanan dosyaların kodlama çerezi olmamalıdır. Latin-1 (veya UTF-8) yalnızca bir yorum veya doktora yazısının Latin-1 gerektiren bir yazar adından bahsetmesi gerektiğinde kullanılmalıdır; aksi takdirde, \ x, \ u veya \ U çıkış karakterleri kullanmak ASCII olmayan verileri dize değişmezlerine eklemenin tercih edilen yoludur.


30

Basitçe açıklayayım: python 2'de, dizeyi 2 farklı tipte saklayabilirsiniz.

Birincisi , python'da str tipi olan ASCII , 1 bayt bellek kullanıyor. (256 karakter, çoğunlukla İngilizce alfabe ve basit semboller depolar)

2 türüdür UNICODE olduğunu unicode Python türü. Unicode her türlü dili saklar.

Varsayılan olarak, python str türünü tercih eder, ancak dizeyi unicode türünde saklamak istiyorsanız, u'text ' gibi metnin önüne u koyabilir veya bunu unicode (' metin ') diyerek yapabilirsiniz

Yani u dökme bir işlevi çağırmak için sadece kısa yoludur str için unicode . Bu kadar!

Şimdi r bölümü, bilgisayara metnin ham metin olduğunu söylemek için metnin önüne koydunuz, ters eğik çizgi kaçan bir karakter olmamalıdır. r '\ n' yeni bir satır karakteri oluşturmaz. Sadece 2 karakter içeren düz bir metindir.

Eğer dönüştürmek istiyorsanız str için unicode ve orada da ham metin koymak, kullanım ur nedeniyle ru bir hata yükseltecektir.

ŞİMDİ, önemli kısım:

Bir ters eğik çizgiyi r kullanarak depolayamazsınız , tek istisna budur. Yani bu kod hata üretir: r '\'

Ters eğik çizgi (yalnızca bir tane) saklamak için '\\'

Eğer 1'den fazla karakter saklamak istiyorsanız yine kullanabilirsiniz r gibi r '\\' beklendiği gibi 2 ters eğik çizgi üretecek.

Ben r neden bir ters eğik çizgi depolama ile çalışma nedenini bilmiyorum ama nedeni henüz kimse tarafından açıklanmadı. Umarım bir hatadır.


9
Sadece r'\'yasadışı olmadığını fark edeceksiniz , hatta '\'herhangi bir ipin kuyruğuna bile bir tane koyamazsınız . Tıpkı r'xxxxxx\'yasadışı bir ip gibi.
Diverger

python 3 ne olacak?
Krissh

1
@Krissh Tüm python 3 dizeleri Unicode desteklenir. Türü olacak str. Daha iyi anlamak için daha fazla bilgiyi
off99555

4

Belki bu açıktır, belki değil, ama x = chr (92) çağırarak '\' dizesini yapabilirsiniz

x=chr(92)
print type(x), len(x) # <type 'str'> 1
y='\\'
print type(y), len(y) # <type 'str'> 1
x==y   # True
x is y # False

4
x is ypython3 doğru mu değerlendiriyor?
Habeeb Perwad

5
@HabeebPerwad, bunun nedeni dize stajı . Stajyerlik nedeniyle x is ydeğerlendirilen gerçeğe asla güvenmemelisiniz True. Bunun yerine kullanın x == y(eğer x ve y'nin tek bir bellek konumunda saklanan aynı nesne olup olmadığını kontrol etmiyorsanız).
Lucubrator

4

Unicode dize değişmez değerleri

Unicode dize değişmezleri (ön ekli dize değişmez değerleri u) artık Python 3'te kullanılmamaktadır . Bunlar hala geçerlidir, ancak yalnızca Python 2 ile uyumluluk amaçlıdır .

Ham dize değişmez değerleri

Eğer ingilizce harfler veya sayılar gibi sadece kolayca tip bulunmayan karakterden oluşan değişmez bir dize oluşturmak istiyorsanız, onları yazabilirsiniz: 'hello world'. Ancak, daha egzotik karakterler de eklemek istiyorsanız, geçici bir çözüm kullanmanız gerekir. Geçici çözümlerden biri Escape dizileridir . Bu şekilde, örneğin \n, dizgi hazır bilginize kolayca yazabilen iki karakter ekleyerek dizenizdeki yeni bir satırı temsil edebilirsiniz . Bu nedenle, 'hello\nworld'dizeyi yazdırdığınızda, kelimeler ayrı satırlara yazdırılır. Bu çok kullanışlı!

Öte yandan, kaçış dizileri içeren bir dize değişmezi oluşturmak istediğinizde, ancak bunların Python tarafından yorumlanmasını istemediğiniz bazı durumlar vardır. Ham olmalarını istiyorsunuz . Şu örneklere bak:

'New updates are ready in c:\windows\updates\new'
'In this lesson we will learn what the \n escape sequence does.'

Bu gibi durumlarda, dizgi değişmezine şu rkarakterle önek ekleyebilirsiniz : r'hello\nworld've hiçbir kaçış dizisi Python tarafından yorumlanmaz. Dize, tam olarak oluşturduğunuz gibi yazdırılır.

Ham dize değişmezleri tamamen "ham" değil mi?

Birçok kişi ham dize değişmezlerinin "tırnaklar arasına yerleştirilen herhangi bir şey Python tarafından yok sayılır" anlamında ham olmasını bekler . Bu doğru değil. Python hala tüm kaçış dizilerini tanıyor, sadece yorumlamıyor - bunun yerine değişmeden kalıyor. Bu, ham dize değişmezlerinin hala geçerli dize değişmezleri olması gerektiği anlamına gelir .

Gönderen sözcük tanımı bir dize arasında:

string     ::=  "'" stringitem* "'"
stringitem ::=  stringchar | escapeseq
stringchar ::=  <any source character except "\" or newline or the quote>
escapeseq  ::=  "\" <any source character>

Açık bir tırnak karakteri içeren 'hello'world'ya da ters eğik çizgi ile biten dize değişmezlerinin (ham ya da değil) geçerli olmadığı açıktır 'hello world\'.

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.