Co robi znak "b"przed literalnym łańcuchem?
Wygląda na to, że prawidłowa składnia jest następująca:
my_string = b'The string'
Chciałbym wiedzieć:
- co oznacza ten
b
znak przed łańcuchem? - jakie są efekty jego używania?
- jakie są odpowiednie sytuacje, aby z niego korzystać?
Znalazłem podobne pytanie tutaj na SO, ale to pytanie dotyczy PHP, i stwierdza, że b
jest używany do wskazania, że łańcuch jest binarny, w przeciwieństwie do Unicode, co było potrzebne, aby Kod był zgodny z wersją PHP
Znalazłem tę dokumentację na stronie Pythona O używanie znaku u
w tej samej składni, aby określić ciąg znaków jako Unicode. Niestety, nigdzie w tym dokumencie nie ma wzmianki o znaku b.
Również, tak z ciekawości, czy jest więcej symboli niż b
i u
, które robią inne rzeczy?
9 answers
Cytuję Python 2.x dokumentacja :
Przedrostek " b " lub " B " jest ignorowany w Pythona 2; oznacza to, że literał powinien stać się literałem bajtów w Pythonie 3 (np. gdy kod jest automatycznie konwertowane z 2to3). A po przedrostku " u " lub " b " może następować przedrostek "r".
Dokumentacja Pythona 3 stwierdza:
Literały bajtów są zawsze poprzedzone ' b ' lub 'B'; zamiast tego tworzą instancję typu bajtów typu str. Mogą one zawierać tylko znaki ASCII; bajty o wartości liczbowej 128 lub większej muszą być wyrażone za pomocą znaków specjalnych.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-11-07 03:46:20
Python 3.x daje wyraźne rozróżnienie między typami:
-
str
='...'
literały = ciąg znaków Unicode (Latin-1, UCS-2 lub UCS-4, W zależności od najszerszego znaku w łańcuchu) -
bytes
=b'...'
literały = ciąg oktetów (liczb całkowitych od 0 do 255)
Jeśli znasz:
- Java lub C#, pomyśl o
str
jakoString
ibytes
jakobyte[]
; - SQL, pomyśl o
str
Jak oNVARCHAR
ibytes
jakoBINARY
lubBLOB
; - rejestr systemu Windows, pomyśl o
str
jakoREG_SZ
ibytes
jakoREG_BINARY
.
Jeśli znasz C (++), zapomnij o wszystkim, czego się nauczyłeś o char
i łańcuchach, ponieważ znak nie jest bajtem. Ten pomysł jest od dawna przestarzały.
Używasz str
, Gdy chcesz reprezentować tekst.
print('שלום עולם')
Używasz bytes
, gdy chcesz reprezentować dane binarne niskiego poziomu, takie jak struktury.
NaN = struct.unpack('>d', b'\xff\xf8\x00\x00\x00\x00\x00\x00')[0]
Możesz zakodować a str
do bytes
obiektu.
>>> '\uFEFF'.encode('UTF-8')
b'\xef\xbb\xbf'
I możesz dekodować bytes
na str
.
>>> b'\xE2\x82\xAC'.decode('UTF-8')
'€'
Ale nie można swobodnie mieszać tych dwóch typów.
>>> b'\xEF\xBB\xBF' + 'Text with a UTF-8 BOM'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't concat bytes to str
Notacja b'...'
jest nieco myląca, ponieważ pozwala na podanie bajtów 0x01-0x7f za pomocą znaków ASCII zamiast liczb szesnastkowych.
>>> b'A' == b'\x41'
True
Ale muszę podkreślić, znak nie jest bajtem .
>>> 'A' == b'A'
False
W Pythonie 2.x
Pre-3.0 wersje Pythona brakowało tego rodzaju rozróżnienia między tekstem i dane binarne. Zamiast tego było:
-
unicode
=u'...'
literały = sekwencja znaków Unicode = 3.xstr
-
str
='...'
literały = sekwencje zniekształconych bajtów / znaków- zazwyczaj tekst, zakodowany w jakimś nieokreślonym kodowaniu.
- ale również używane do reprezentowania danych binarnych, takich jak wyjście
struct.pack
.
W celu ułatwienia 2.x do 3.X transition, literalna składnia b'...'
została ponownie zaimportowana do Pythona 2.6, aby umożliwić rozróżnianie ciągów binarnych (które powinny być bytes
w 3.x) z ciągów tekstowych (które powinny być str
W 3.x). Przedrostek b
nie robi nic w 2.x, ale mówi skryptowi 2to3
, aby nie konwertował go na ciąg Unicode w 3.x.
Więc tak, b'...'
literały w Pythonie mają ten sam cel, co w PHP.
Również, tak z ciekawości, są tam więcej symboli niż b i u, które robią inne rzeczy?
Prefiks r
tworzy surowy ciąg znaków (np. r'\t'
jest odwrotnym ukośnikiem + t
zamiast tabulacji), a potrójne cudzysłowy '''...'''
lub """..."""
pozwalają na Wielowierszowe literały ciągu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-11-17 19:35:49
B oznacza łańcuch bajtów.
Bajty są rzeczywistymi danymi. Ciągi są abstrakcją.
Jeśli posiadasz obiekt wielo-znakowy i przyjmujesz pojedynczy znak, będzie to ciąg znaków, który może mieć więcej niż 1 bajt w zależności od kodowania.
Jeśli wziąłbyś 1 bajt z łańcuchem bajtów, otrzymałbyś pojedynczą 8-bitową wartość od 0-255 i może ona nie reprezentować pełnego znaku, jeśli te znaki ze względu na kodowanie były > 1 bajt.
TBH użyłbym stringów chyba Miałem jakiś konkretny powód niskiego poziomu, aby używać bajtów.
Od strony serwera, jeśli wyślemy jakąkolwiek odpowiedź, zostanie ona wysłana w formie typu byte, więc pojawi się w kliencie jako b'Response from server'
Aby pozbyć się b'....'
wystarczy użyć poniższego kodu:
Plik serwera:
stri="Response from server"
c.send(stri.encode())
Plik klienta:
print(s.recv(1024).decode())
Następnie wydrukuje Response from server
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-08-28 10:30:18
Oto przykład, w którym brak b
rzuciłby wyjątek TypeError
w Pythonie 3.x
>>> f=open("new", "wb")
>>> f.write("Hello Python!")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' does not support the buffer interface
Dodanie prefiksu b
rozwiązałoby problem.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-08-28 10:31:56
Zamienia go w bytes
literał (lub str
w 2.x) i jest ważny dla 2,6+.
Prefiks r
powoduje, że ukośniki są "niezainterpretowane" (Nie ignorowane, a różnica ma znaczenie).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-07 18:16:23
Oprócz tego, co powiedzieli inni, zauważ, że pojedynczy znak w unicode może składać się z wielu bajtów.
Sposób działania unicode polega na tym, że zastosowano stary format ASCII (7-bitowy kod, który wygląda jak 0xxx xxxx) i dodano sekwencje multi-bajtów gdzie wszystkie bajty rozpoczynają się od 1 (1xxx xxxx), aby reprezentować znaki poza ASCII, tak aby Unicode był kompatybilny wstecz z ASCII.
>>> len('Öl') # German word for 'oil' with 2 characters
2
>>> 'Öl'.encode('UTF-8') # convert str to bytes
b'\xc3\x96l'
>>> len('Öl'.encode('UTF-8')) # 3 bytes encode 2 characters !
3
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-07 12:16:05
Odpowiedź na pytanie brzmi:
data.encode()
I w celu jej dekodowania (usuń b
, bo czasami nie potrzebujesz)
Użycie:
data.decode()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-02-14 01:07:10
Możesz użyć JSON, aby przekonwertować go do słownika
import json
data = b'{"key":"value"}'
print(json.loads(data))
{"klucz": "wartość"}
Piersiówka:
To jest przykład z kolby. Uruchom to na linii terminala:
import requests
requests.post(url='http://localhost(example)/',json={'key':'value'})
W flask/routes.py
@app.route('/', methods=['POST'])
def api_script_add():
print(request.data) # --> b'{"hi":"Hello"}'
print(json.loads(request.data))
return json.loads(request.data)
{'klucz': 'wartość'}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-05-14 12:45:01