Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Bitwise Operator Overloading

00:00 In the previous lesson, I showed you how byte orders are related to boiled eggs. In this lesson, I’ll show you how to use the special methods inside of Python objects to overload bitwise operators.

00:13 Everything in Python is an object. All the interactions between objects that look like operations—adding, subtracting, comparisons, et cetera—are actually mappings to special methods on those objects.

00:25 These special methods all start with double underscores (__), sometimes referred to as dunder. For bitwise operators, the special methods are .__and__(), dunder .__or__(), .__xor__(), and .__invert__().

00:40 Let’s go play with these in the REPL. In the top window here, I’ve created a new class called FourBit. In the spirit of the four-bit adder in a previous lesson, I’ve created an object that stores only four bits. Note the little bit of trickiness in the declaration of the class.

00:59 I’m overloading the int class. I’m doing that so that I don’t have to write as many overloads. For example, all the comparison operations can be handled by the parent class.

01:10 The int class uses a variable called num to store the value, so the initializer starting on line 3 does the same thing. I’ve added a quick check in the initializer to make sure nobody tries to create a four-bit object with a value that is bigger than what can be stored in four bits. Let me start out by importing this into the REPL,

01:34 and I’ll create a FourBit object. Because I’ve overloaded the special method .__repr__() on line 13, the REPL prints out this object in a friendly format.

01:49 Any integer can be passed into FourBit(). Let me just scroll down on the code. The first special method I want to talk about is .__add__().

01:59 This is what is called when two FourBit objects are added together. The other argument is the object being added to this one. Line 18 adds our num value to the other object’s num value, then masks it to make sure it stays as four bits.

02:17 Let me just call it,

02:22 and there you go. 7 plus 2 is 9. I’ve implemented other math operations as well, and you can look at those more closely in the sample code download if you like.

02:32 Let’s move on to the bitwise operators. Line 36 overloads the .__and__() special method. Like .__add__(), it takes an other object.

02:43 A new FourBit is constructed with the values of the two objects AND-ed together. Testing it in the REPL.

02:56 Similar thing for .__or__().

03:05 How about .__xor__()?

03:12 And finally, the .__invert__(), or NOT, operation. In the case of NOT, I’m masking it. I don’t want those pesky higher value bits getting in the way.

03:25 Given our history with the NOT operation and negative values, this one deserves a bit more testing.

03:36 And all those bits flipped to zero. Nice! For a little homework, you could take the code from the FourBit adder from the skippable section and re-implement the .__add__() method to use your digital circuit simulator.

03:51 The overloading I’ve done is to make an actual numeric object do bitwise things, but you’re not limited to that. Lots of objects overload bitwise operations to mean different things. For example, the set and frozenset objects overload OR and AND (&) to mean set union and intersection, respectively.

04:13 Python 3.9 added similar use cases to the dictionary object. Well, now. It’s been a long journey. I feel much closer to you than when this all got started. Last up, I summarize all this stuff.

Become a Member to join the conversation.