2.6. Metin ve baytlar¶
Python’ın ham karakter verileri için iki dizi türü vardır:
str– Unicode kod noktalarından oluşan bir dizi. İnsan tarafından okunabilen tüm metinler için kullanılır: dosya yolları, günlük mesajları, JSON yükleri.bytes– 0 – 255 aralığında tam sayılardan oluşan bir dizi. Ham ikili veriler için kullanılır: UART çerçeveleri, görüntü arabellekleri, ağ paketleri, yazmaç değerleri.
Açık bir dönüştürme olmadan karıştırılamazlar. Bir donanım write yöntemine str geçirmek TypeError yükseltir ve tersi de reddedilir.
Bir str Unicode karakterleri saklar; bir bytes ham oktetleri saklar. Aralarında geçiş yapmak kodlama (str → bytes) ve kod çözme (bytes → str) işlemidir.¶
2.6.1. bytes literalleri¶
Bir bytes literali, önüne b eklenmiş dize benzeri bir literaldir:
header = b"OMV"
crlf = b"\r\n"
payload = b"\x01\x02\x03"
Bir bytes literalinin içinde doğrudan yalnızca ASCII karakterlerine izin verilir; ASCII olmayan değerler \xHH onaltılık kaçışları olarak yazılmalıdır.
2.6.2. Kodlama ve kod çözme¶
str.encode()bir dizeyi adlandırılmış bir kodlama kullanarak baytlara dönüştürür (varsayılan"utf-8").bytes.decode()bunun tersini yapar.
>>> "hello".encode()
b'hello'
>>> "héllo".encode()
b'h\xc3\xa9llo' # é is two bytes in UTF-8
>>> b"hello".decode()
'hello'
UTF-8 varsayılandır ve ASCII olmayan karakterler içerebilecek her şey için doğru seçimdir. "ascii" yalnızca verinin düz ASCII olduğu garanti edildiğinde kullanın; böylece ASCII olmayan başıboş bir bayt sessizce geçip gitmek yerine UnicodeError yükseltir.
2.6.3. İndeksleme ve dilimleme¶
Bir bytes değeri indekslendiğinde tek baytlık dizelerin dizisi gibi değil, tam sayılar dizisi gibi davranır:
>>> data = b"abc"
>>> data[0]
97 # the int 97, not 'a'
>>> data[0:1]
b'a' # slicing returns bytes
Yaygın bir hata, data[0] == "a" karşılaştırmasını yapıp sonucun False çıkmasına şaşırmaktır – data[0] tek karakterlik bir dize değil, bir tam sayıdır, dolayısıyla iki değer asla eşleşemez.
2.6.4. ord ve chr – karakterler ve tam sayılar arasında köprü kurma¶
Bir bytes indekslemek bir tam sayı döndürdüğünden, ancak programın geri kalanı muhtemelen karakterler üzerinden düşündüğünden, Python bunlar arasında geçiş için iki yerleşik işlev sağlar:
ord()– tek karakterlik bir dize alır ve onun tam sayı kod noktasını döndürür.chr()– tersi: bir tam sayı verildiğinde, o kod noktasına karşılık gelen tek karakterlik dizeyi döndürür.
>>> ord("a")
97
>>> chr(97)
'a'
>>> ord("A"), chr(0x41)
(65, 'A')
ASCII karakterlerinde kod noktası bayt değerine eşittir, dolayısıyla ord("a") ve b"a"[0] her ikisi de 97 verir. Bu, bayt karşılaştırmalarının gerçekten önemsediğiniz karakter cinsinden okunmasını sağlar:
>>> data = b"abc"
>>> data[0] == ord("a") # instead of the magic number 97
True
Ve chr(), bir baytın yazdırılabilir biçimini görmek istediğinizde günlükleme veya hata ayıklama için kullanışlıdır:
>>> chr(data[0])
'a'
ASCII olmayan karakterler için ord() Unicode kod noktasını döndürür ki bu, kodlanmış biçimdeki herhangi bir tek baytla aynı değildir; bayt gösterimi kodlamaya bağlıdır.
2.6.5. Değiştirilebilir arabellekler için bytearray¶
bytes değişmezdir – her “değişiklik” yeni bir nesne döndürür ve orijinalini olduğu gibi bırakır. Değiştirmeyi, sonuna ekleme yapmayı veya parça parça doldurmayı düşündüğünüz veriler için bytearray kullanın. bytes ile aynı içeriği tutar ancak yerinde değiştirmeyi destekler:
>>> s = b"hello"
>>> s[0] = ord("H")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'bytes' object does not support item assignment
>>> s = bytearray(b"hello")
>>> s[0] = ord("H")
>>> s
bytearray(b'Hello')
2.6.5.1. Bir bytearray oluşturma¶
bytearray yapıcısı çeşitli girdiler kabul eder:
bytearray(8)– 8 sıfır baytlık bir arabellek.bytearray(b"hello")– bir bytes değerinin değiştirilebilir bir kopyası.bytearray("hello", "utf-8")– verilen kodlamayı kullanarak bir dizeden oluşturulan bir bytearray.bytearray([72, 73, 74])– 0 – 255 aralığındaki tam sayılardan oluşan bir diziden oluşturulan bir bytearray (buradab"HIJ").
>>> bytearray(4)
bytearray(b'\x00\x00\x00\x00')
>>> bytearray(b"abc")
bytearray(b'abc')
>>> bytearray("café", "utf-8")
bytearray(b'caf\xc3\xa9')
2.6.5.2. Bir bytearray değiştirme¶
İndeksli ve dilimli atama, tıpkı bir list gibi çalışır:
>>> buf = bytearray(8) # 8 zero bytes
>>> buf[0] = 0xFF # one byte at a time
>>> buf[1:4] = b"ABC" # replace a slice
>>> buf
bytearray(b'\xffABC\x00\x00\x00\x00')
Tek tek baytlar 0 – 255 aralığında tam sayılar olmalıdır; başka bir tür atamak TypeError veya ValueError yükseltir.
Dilim ataması arabelleğin uzunluğunu değiştirebilir. Bir dilimi daha uzun bir değerle değiştirmek bytearray’i büyütür; daha kısa bir değerle değiştirmek onu küçültür. b"" ile değiştirmek dilimi tamamen siler:
>>> buf = bytearray(b"abcdef")
>>> buf[1:3] = b"XYZ" # 2 bytes replaced with 3
>>> buf
bytearray(b'aXYZdef')
>>> buf[1:4] = b"" # delete the inserted run
>>> buf
bytearray(b'adef')
bytearray.append() ve bytearray.extend() yöntemleri, her seferinde tüm arabelleği yeniden ayırmadan sona bayt ekler:
>>> buf = bytearray()
>>> buf.append(0x01)
>>> buf.extend(b"abc")
>>> buf
bytearray(b'\x01abc')
2.6.5.3. Bir bytearray’den okuma¶
İndeksleme, dilimleme, yineleme ve bytes inceleme yöntemleri (bytes.startswith(), bytes.find(), bytes.strip() vb.) hepsi bir bytes değerindeki gibi çalışır. İndeksleme bir tam sayı döndürür; dilimleme başka bir bytearray döndürür:
>>> buf = bytearray(b"OpenMV")
>>> buf[0]
79
>>> buf[0:4]
bytearray(b'Open')
>>> buf.startswith(b"Open")
True
2.6.5.4. bytes ve bytearray arasında dönüştürme¶
bytes ve bytearray, yapıcılarıyla birbirine dönüştürülür. Bir API özellikle belirli bir biçim gerektirdiğinde bunu kullanın:
>>> ba = bytearray(b"hello")
>>> snapshot = bytes(ba) # immutable copy
>>> ba[0] = ord("H")
>>> ba, snapshot
(bytearray(b'Hello'), b'hello')
2.6.5.5. Sıfır kopyalı dilimleme için memoryview¶
Bir bytes veya bytearray dilimlemek normalde baytları yeni bir arabelleğe kopyalar. memoryview aynı baytları kopyalamadan açığa çıkarır:
>>> buf = bytearray(b"OpenMV Cam")
>>> view = memoryview(buf)
>>> view[0:6] # shares storage with buf
<memoryview ...>
>>> bytes(view[0:6]) # materialise as bytes when needed
b'OpenMV'
Bir bytearray üzerindeki bir görünüm aynı zamanda yazılabilirdir – görünümü değiştirmek altta yatan arabelleği değiştirir:
>>> view[0] = ord("o")
>>> buf
bytearray(b'openMV Cam')
Bir dilimi kopyalamak savurgan olacağında memoryview kullanın – tipik olarak aynı büyük arabellek etrafta dolaştırıldığında veya parça parça işlendiğinde. Küçük baytlar üzerinde gündelik dize tarzı işlemler için düz dilimleme yeterlidir.