Introduction¶
Computers work exclusively with binary values: 0 and 1, called bits.
Every file on your computer is just a sequence of bits. Every message
that gets sent between computers is just a sequence of bits. Python
hides this from you most of the time–when you write True, 12,
or "Chris", Python doesn’t normally show you the bits underneath.
easybits provides the Bits class, which lets you
see and manipulate those bits directly.
Creating bits¶
The Bits class can be built from several different
kinds of values. The simplest is a string of 0 s and 1 s:
from easybits import Bits
b = Bits('1010')
print(b) # 1010
You can also build bits from Python’s other building blocks. A boolean becomes a single bit:
Bits(True) # 1
Bits(False) # 0
Bytes become eight bits each:
Bits(b'a') # 01100001
Booleans¶
Because Bits is built on top of the bitarray
package, it supports the same bitwise operators you’d find in a
lower-level language: ~ (NOT), & (AND), | (OR), ^
(XOR), and the shift operators << and >>:
a = Bits('1100')
b = Bits('1010')
a & b # 1000
a | b # 1110
a ^ b # 0110
~a # 0011
a << 1 # 1000
a >> 1 # 0110
Integers¶
Bits represent numbers in binary, where each position is worth twice as much as the position to its right: 1, 2, 4, 8, and so on. Because an integer’s bits don’t have a natural length the way a boolean’s single bit does, easybits requires you to say how many bits to use:
Bits(12, length=8) # 00001100
Negative numbers are represented using two’s complement, which is
why easybits always treats integers as signed. To recover the
integer value of some bits, use the .int property:
b = Bits(-12, length=16)
b.int # -12
You can add and subtract bits just like integers, as long as both operands have the same length:
Bits(5, length=8) + Bits(3, length=8) # 00001000
Bits(5, length=8) - Bits(3, length=8) # 00000010
This bitwise addition is implemented from scratch, carry bit and all, so you can watch how addition really happens at the level of circuits.
Text¶
Text is the trickiest of the three. ASCII, an early standard for representing text as bits, only has room for 128 characters–enough for English, but not for the world’s other languages, let alone emoji. Unicode, and its common encoding UTF-8, supports more than 150,000 characters, covering world languages and emoji alike. Because of this, encoding text requires choosing an encoding, and easybits lets you say which one to use:
Bits("Chris") # ASCII by default
Bits("\N{SMILING FACE WITH HEART-EYES}", encoding='utf8')
To go the other direction–from bits back to text–use the .ascii
property, or decode the .bytes yourself with whichever encoding
you used to create the bits:
b = Bits("Chris")
b.ascii # 'Chris'
Inspecting bits¶
However you created your bits, you can always ask what they look like
as a different kind of value, using the Bits
properties:
.boolreturns a list of booleans, one per bit.intinterprets the bits as a signed integer.bytesreturns the raw bytes.asciidecodes those bytes as ASCII text
The API describes each of these, along with the rest of the
Bits class, in full detail.