# Python bin(): Binary Values Handled with Ease The Python bin() method converts an integer value to a string representation of its binary representation. Python’s bin() method can also be used to return the binary representation of any object that has implemented a valid __index__ method.

The Python `bin()` built-in function is a useful tool in translating between languages, domains, and understanding the fundamentals of how low-level data is represented. In this article, you will learn the basic usage of the `bin()` function, some advanced uses, and ways in which one might break things using it.

TL;DR – The Python `bin()` function returns a string representation of an integer’s binary value.

```# Define a number
>>> number = 42
42

# Use bin to get binary value
>>> bin(number)
0b101010

# Check the type
>>> type(bin(number))
<class 'str'>

# Only works for integers
>>> bin(42.0)
TypeError: 'float' object cannot be interpreted as an integer```

## Basic Use

The Python `bin()` function can be used for a range of applications where binary values are of interest. The simplest use-case is to return the binary value of an integer value—the only valid numerical representation for which the `bin()` function will accept. Let’s see that in action:

```# Define a number
number = 42

# Get its binary value via bin()
bin_value = bin(42)

# Display the value, check the type
print(bin_value)
print(type(bin_value))

# Output
0b101010
<class 'str'>

```

A few things to note here:

1. The return value is a `str` object
2. The return value is prefixed with 0b
3. Six `1's` and `0's` are used to represent values, the absolute minimum required.

Python’s bin() function will show you the binary representation of a number but there isn’t a lot you can do with that information explicitly. For example, let’s try to convert a binary string to a hexadecimal value:

```# Convert to hexadecimal
hex_value = hex(bin_value)

# Result
TypeError: 'str' object cannot be interpreted as an integer```

Yikes. So that isn’t great news but it is expected behavior given the implementation of the hex() function. Consider how the official Python documentation describes its use:

Convert an integer number to a lowercase hexadecimal string prefixed with “0x”.

If our true goal was to get the hexadecimal value of 42 this would be a silly example—we’d just skip the `bin(`) function altogether as such: `hex(42)`. But we’re learning here, so let’s ignore that hiccup and see some more ridiculous examples.

Check out the article on how to convert hexadecimal values to binary in Python for more examples of how the `bin()` and `hex()` functions work in concert (also how they break things sometimes!)

## Using Bin on Non-Integer Objects

Recall that Python represents all data an object. This is essential to understand how the Python `bin()` function will interact with other objects.  Some language features like operators and conditionals are special cases but, for everything else, Python models them as objects with a slew of attributes and methods available. For example, let’s check under the hood of our humble value 42 using the `dir()` method:

```# Get a list of valid attributes for our int 'object'
>>> dir(42)

['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'as_integer_ratio', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']
```

Wow. There’s a lot going on here. Don’t worry I’m not going to try and unpack all that. Just know; everything in Python has a big long list of associated attributes and usually methods as well.

For now, the only attribute we’ll focus on is the `__index__` attribute. This language feature was made available via PEP357 circa Python version 2.5 (early 2006) and is described as follows:

This PEP proposes adding … an __index__ special method so that arbitrary objects can be used whenever integers are explicitly needed in Python …

In other words, we can make any custom object work with the `bin()` function by implementing a custom `__index__` method. Consider the following:

```class CustomHex:
"""A custom hexadecimal representation of an integer"""
def __init__(self, num: int):
self.value = hex(num)

# Define an integer value
num = 42

# Show as built-in hex
print(hex(42))

>>> 0x2a

# Create custom hex object
better_hex = CustomHex(num)

# See hex value
print(better_hex.value)

>>> 0x2a

# Get binary value
print(bin(better_hex))

>>> TypeError: 'CustomHex' object cannot be interpreted as an integer
```

Here I’ve created a custom `CustomHex` class that converts an integer’s value and stores it internally as a hexadecimal string referenced by the object’s `self.value` attribute. When this object is passed to the `bin()` method it results in an `TypeError`.

This error results because our object doesn’t let Python know how it should be represented as an integer. Let’s see what happens when we implement a custom `__index__` method as the documentation suggests:

```class CustomHex:
"""A custom hexadecimal representation of an integer"""
def __init__(self, num: int):
self.value = hex(num)

def __index__(self):
"""Custom method to define the integer representation"""
return int(self.value, 16)

# Instantiate a new CustomHex object
better_hex = CustomHex(42)

# Get binary value
print(bin(better_hex))

>>> 0b101010```

That’s a bingo! This example illustrates, albeit in another contrived imagining, how the `bin()` function can be coupled with the `__index__` attribute to represent just about anything as a binary string in Python. Is this a common case? Not in my experience.

## Common Cases

Python’s `bin()` function serves its purpose well. There are a number of common case uses in which this method is used. Whether you want to convert an int to a binary string, a string to binary, or a binary string to an int—the Python `bin()` built-in function can help. In some cases, it may require the use of other built-ins such as the `hex()` function to translate between values. Let’s take `bin()` out for a spin().

### Convert an Int to Binary

Integers are the classic use case for Python’s bin() function. They can be used directly to extract a binary representation as such:

```# Get the binary value of an integer
>>> bin(42)

0b101010
```

This returns a `str` object using as few 1’s and 0’s as possible. Note the prefix of 0b. There is no built-in way to remove that notation but, using string indexing, it can be done easy enough:

```>>> bin(42)[2:]

101010```

Easy enough. Let’s consider how one might return the binary representation of a string.

### String to Binary

Keep in mind that everything in non-quantum computing boils down to 1’s and 0’s. Strings are no exception. The amount of 1’s and 0’s required to represent text quickly becomes impractical but can still be seen easily enough using Python’s `bin()` function. For this, we’ll have to use Python’s ord() function to get an integer value of each character in a string.

```>>> "-".join(bin(ord(c))[2:] for c in 'overcoded')

1101111-1110110-1100101-1110010-1100011-1101111-1100100-1100101-1100100```

(Uh oh, a one-liner.) Here I’ve created a binary string for the word `overcoded` with each character’s binary value separated by a single dash for visual clarity and dropped the leading `0b` as well. The hoop-jumping of using the ord() function is, again, to satisfy Python’s bin() function’s need for an integer value.

### Binary to Int

Python’s `bin()` function demands an integer value but can a binary value be easily converted into an integer? Let’s consider the binary string of the integer value `42` given to us by Python’s `bin()` function:

```val = bin(42)
print(val, type(val))

>>> 0b101010 <class 'str'>

int(val)

>>> ValueError: invalid literal for int() with base 10: '0b101010'
```

It would seem that Python’s `bin()` function is good at giving orders regarding integer values but not so good at taking orders. Let’s see if we can come up with a work-around.

```# Get the binary value of a number
bin_value = bin(42)
print(bin_value, type(bin_value))

0b101010 <class 'str'>

# Get Integer Value from Binary
int_value = int(bin_value, 2)
print(int_value, type(int_value))

42 <class 'int'>

# Convert int back to binary
bin_again = bin(int_value)
print(bin_again, type(bin_again))

0b101010 <class 'str'>

# Compare
print(bin_value == bin_again)

True```

This circuitous sequence of events demonstrates the process of converting a binary value to an integer value in python and back again. I don’t know why one might want to do this but it does illustrate the underpinnings and interplay of Python’s bin and int features well.

Note: In using the int type to cast our binary string to an integer I used a second argument with the value `2`. This instructs Python’s int that the first argument is a numerical representation in base 2 notation. If we’d been converting from hexadecimal a value of 16 would have been used. We have a useful article on how computers represent numbers if you want to learn more on that subject.

### Convert Binary to String

Python’s `bin()` function can be used to convert a binary value, represented as a string of 1’s and 0’s or an integer value, to a string of characters. This involves some consideration for encoding, but I’m going to side-step most of that here. We’ll be assuming that ASCII characters are intended.

```# Convert a binary value to a string
>>> str(1111010), type(str(1111010))

1111010, <class 'str'>
```

Well, that isn’t very useful. The issue here is that `1111010` looks like a binary value but, in fact, is an integer value. These values aren’t the same under the hood and we need to offer Python some clarification regarding our intent. Namely, we need to explicitly express that our integer value is to be interpreted as the binary notation for an ASCII-format character.

```# Define a character
char = 'z'
print(char, type(char))

>>> z <class 'str'>

# Get the binary value
char_bin = bin(ord(char))
print(char_bin, type(char_bin))

>>> 0b1111010 <class 'str'>

# Convert binary repr to
# explict integer value
exp_int = int(char_bin[2:])
print(exp_int, type(exp_int))

>>> 1111010 <class 'int'>

# Interpret an integer representation
# of a binary value as actual binary
integer_value = int(str(exp_int), 2)
print(integer_value, type(integer_value))

>>> 122 <class 'int'>

# Convert our actual integer to an
# ASCII character
char_again = chr(integer_value)
print(char_again, type(char_again))

>>> z <class 'str'>

# Compare against initial value
print(char == char_again)

>>> True```

I’ll be honest—that was a bit of a headache. The issue comes from trying to represent a binary value as that integer value explicitly. The binary value `1111010` does not equal the integer value of `1111010`. Rather, the binary value `1111010` represents the integer value `122`. Keep in mind, that’s because our initial binary value is in Base 2 notation. You can’t just magically represent a base 2 number as a base 10 value without undergoing some conversion process—at least not without corrupting data.

This example isn’t by any means reflective of any common case that I’ve come across. The most applicable use I can imagine would be for a script that accepted binary data as input and needed to convert it into a different notation. That’s a common enough requirement but I don’t often see engineers jumping into Python to accomplish such a feat.

## Review

Python’s `bin()` function is a simple enough function but, as with many of the simple ones, there is more to the story. The cases of feeding `bin()` erroneously representative numbers (non-converted integer values for example) or objects without `__index__` attributes implemented can wreak havoc and result in `TypeErrors` that aren’t always clear.

The utility `bin()` provides is incredibly useful as an introspective and learning tool. I’ve used it countless times to debug data from other projects (here’s looking at you, MIPS) and to automate the decoding of network transmission data. It’s not something that most applications need for real-time use but still, one of the many features that make Python one of the most versatile programming languages available today.

BSc Graphic Comm. NSCU, BSc CS Candidate WCU. Life-long learner and entrepreneur specializing in design, digital marketing, and web app development. Fascinated by natural systems, concurrency, and the nature of consciousness.