114 lines
3.5 KiB
ReStructuredText
114 lines
3.5 KiB
ReStructuredText
.. _introduction:
|
|
|
|
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 :class:`~easybits.Bits` class, which lets you
|
|
see and manipulate those bits directly.
|
|
|
|
Creating bits
|
|
-------------
|
|
|
|
The :class:`~easybits.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 :class:`~easybits.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 :class:`~easybits.Bits`
|
|
properties:
|
|
|
|
- ``.bool`` returns a list of booleans, one per bit
|
|
- ``.int`` interprets the bits as a signed integer
|
|
- ``.bytes`` returns the raw bytes
|
|
- ``.ascii`` decodes those bytes as ASCII text
|
|
|
|
The :ref:`api` describes each of these, along with the rest of the
|
|
:class:`~easybits.Bits` class, in full detail.
|