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ć:

  1. co oznacza ten b znak przed łańcuchem?
  2. jakie są efekty jego używania?
  3. 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?

Author: Arsen Khachaturyan, 2011-06-07

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.

 474
Author: NPE,
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:

Jeśli znasz:

  • Java lub C#, pomyśl o str jako String i bytes jako byte[];
  • SQL, pomyśl o str Jak o NVARCHAR i bytes jako BINARY lub BLOB;
  • rejestr systemu Windows, pomyśl o str jako REG_SZ i bytes jako REG_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.x str
  • 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.

 801
Author: dan04,
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.

 29
Author: ,
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:34:03

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

 21
Author: Nani Chintha,
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.

 13
Author: user3053230,
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 rpowoduje, że ukośniki są "niezainterpretowane" (Nie ignorowane, a różnica ma znaczenie).

 10
Author: Ignacio Vazquez-Abrams,
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
 8
Author: xjcl,
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()
 3
Author: Billy,
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ść'}

 2
Author: Karam Qusai,
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