2014-07-19 23 views
5

Câu hỏi sau nảy sinh vì tôi đang cố gắng sử dụng các chuỗi bytes làm các giá trị khóa và giá trị byte mà tôi hiểu là bằng nhau không được coi là bằng nhau.Python So sánh các byte byte

Tại sao mã python sau không được so sánh bằng nhau - không phải hai biểu diễn tương đương này của cùng một dữ liệu nhị phân (ví dụ được chọn để tránh endianess)?

b'0b11111111' == b'0xff' 

Tôi biết những điều sau đây đánh giá đúng, chứng minh sự tương đương:

int(b'0b11111111', 2) == int(b'0xff', 16) 

Nhưng tại sao lực lượng python tôi để biết các đại diện? Nó liên quan đến endian-ness? Có cách nào dễ dàng để ép buộc chúng so sánh tương đương với việc chuyển đổi tất cả thành ví dụ hay không, ví dụ: hex literals? Bất cứ ai có thể đề xuất một phương pháp minh bạch và rõ ràng để di chuyển giữa tất cả các đại diện trong một (phần nào) nền tảng độc lập cách (hoặc tôi hỏi quá nhiều)?

Edit:

Với những ý kiến ​​dưới đây, nói rằng tôi muốn thực sự chỉ một cuốn từ điển sử dụng 8 bit dưới dạng b'0b11111111', thì tại sao con trăn mở rộng nó đến mười byte và làm thế nào để ngăn chặn điều đó?

Đây là một phần nhỏ hơn của cấu trúc dữ liệu cây lớn và mở rộng chỉ mục của tôi theo hệ số 80 có vẻ như một sự lãng phí rất lớn của bộ nhớ.

Trả lời

6

Byte có thể đại diện cho bất kỳ số nào của sự vật. Python không thể và sẽ không đoán những gì byte của bạn có thể mã hóa.

Ví dụ: int(b'0b11111111', 34)cũng giải thích hợp lệ, nhưng cách diễn giải đó không bằng hex FF.

Số lượng giải thích trên thực tế là vô tận. Các byte có thể đại diện cho một loạt các điểm mã ASCII, hoặc màu sắc hình ảnh, hoặc nốt nhạc.

Cho đến khi bạn áp dụng một cách rõ ràng một cách giải thích, đối tượng byte gồm chỉ của chuỗi giá trị trong khoảng 0-255, và các đại diện văn bản của những byte sử dụng ASCII nếu có biểu diễn dưới dạng văn bản in:

>>> list(bytes(b'0b11111111')) 
[48, 98, 49, 49, 49, 49, 49, 49, 49, 49] 
>>> list(bytes(b'0xff')) 
[48, 120, 102, 102] 

Các chuỗi byte đó không bằng nhau.

Nếu bạn muốn diễn giải các chuỗi này một cách rõ ràng dưới dạng số nguyên, sau đó sử dụng ast.literal_eval() để giải thích giải mã giá trị văn bản; luôn bình thường hóa đầu tiên trước khi so sánh:

>>> import ast 
>>> ast.literal_eval(b'0b11111111'.decode('utf8')) 
255 
>>> ast.literal_eval(b'0xff'.decode('utf8')) 
255 
+0

Nhưng không phải '0b' chỉ ra rằng chữ' byte' được dự định là biểu diễn nhị phân, bất kể cách bạn diễn giải nó như thế nào? –

+1

@MatthewHemke: Nó chỉ có nghĩa là bạn có một giá trị byte 48 theo sau là một giá trị byte 98. Những * xảy ra * để có thể hiểu được như là các chữ cái ASCII '0' và' b'. –

+0

Nếu đó là trường hợp, làm thế nào để tôi thực hiện là vì vậy mà tôi nhận được chuỗi byte được chính xác 1 byte mà tôi có nghĩa là? –

4

b'0b11111111' gồm 10 byte:

In [44]: list(b'0b11111111') 
Out[44]: ['0', 'b', '1', '1', '1', '1', '1', '1', '1', '1'] 

trong khi b'0xff' bao gồm 4 byte:

In [45]: list(b'0xff') 
Out[45]: ['0', 'x', 'f', 'f'] 

Rõ ràng, họ không phải là đối tượng tương tự.

Giá trị của Python mang tính giải thích.(Rõ ràng là tốt hơn ngụ ý.) Nó không giả định rằng b'0b11111111' nhất thiết phải là biểu diễn nhị phân của một số nguyên. Nó chỉ là một chuỗi các byte. Cách bạn chọn để giải thích nó phải được tuyên bố rõ ràng.

+0

Chuỗi byte thực tế có, nhưng dữ liệu mà chúng đại diện là giống nhau không? Hoặc là các chuỗi byte tự trở thành giá trị khi chúng được diễn giải bằng ví dụ: đánh giá 'int ('', base)'. –

+0

Có, chuỗi byte không giống như giá trị số nguyên. Hàm 'int' chuyển đổi các byte thành' int' (và cơ số phải được chỉ định). – unutbu

Các vấn đề liên quan