What is bitwise operator overloading in Python?

Overview

Operator overloading means giving extended meaning to an operator beyond its predefined meaning. It provides an additional ability for any operator to react depending upon the scenario.

For instance, the + operator can be used to add two integer values to concatenate two or more strings. Hence, it is called operator overloading because, in a standard string library, the + operator is overloaded for concatenation.

Let's take a look at bitwise operator overloading in detail.

The AND operator

Let's look at an example of the bitwise AND operator's overloading.

# Python program to demonstrate
# operator overloading
class Test():
def __init__(self, value):
self.value = value
# magic function to perform logical AND
def __and__(self, obj):
print("Overloaded AND Operator")
if isinstance(obj, Test):
return self.value & obj.value
else:
raise ValueError("Must be an instance of Test class")
# Driver's code
if __name__ == "__main__":
a = Test(9) # 0000 1001
b = Test(12) # 0000 1100
print(a & b)

Explanation

  • Lines 3–12: We create a Test class. It has a magic method __and__() to perform the bit-wise logical AND operation.
  • Lines 9–10: isinstance(obj, Test) will check whether the argument object obj is of the Test.class type or not. We then perform the bitwise logical AND
  • Line 12: When the argument is of a different type, it returns a value error.
    • Lines 15–18: We create two objects of the Test class, a and b. We then use the above-created function to perform logical AND.

    The OR operator

    Below, we have an example of bitwise OR operator's overloading.

    # Python program to demonstrate
    # operator overloading
    class Test():
    def __init__(self, value):
    self.value = value
    # magic function to perform logical OR
    def __or__(self, obj):
    print("Overloaded OR Operator")
    if isinstance(obj, Test):
    return self.value | obj.value
    else:
    raise ValueError("Must be an instance of Test class")
    # Driver's code
    if __name__ == "__main__":
    a = Test(9) # 0000 1001
    b = Test(12) # 0000 1100
    print(a | b)

    Explanation

    • Lines 3–12: We create a Test class. It has the method __or__() to perform the bitwise logical OR operation.
    • Lines 9–10: isinstance(obj, Test) will check whether the argument object obj is of Test class type or not. We then perform the bitwise logical OR.
    • Line 12: When the argument is of a different type, it will return a value error.
      • Lines 15–18: We create two objects of Test class, a and b. Finally, we use the above-created function to perform the logical OR.

      The XOR operator

      Below, we see an example of bitwise XOR operator's overloading:

      # Python program to demonstrate
      # operator overloading
      class Test():
      def __init__(self, value):
      self.value = value
      # magic function to perform logical XOR
      def __xor__(self, obj):
      print("Overloaded XOR Operator")
      if isinstance(obj, Test):
      return self.value ^ obj.value
      else:
      raise ValueError("Must be an instance of Test class")
      # Driver's code
      if __name__ == "__main__":
      a = Test(9) # 0000 1001
      b = Test(12)# 0000 1100
      print(a ^ b)

      Explanation

      • Lines 3–12: We create a Test class. It has a method __xor__() to perform the bitwise logical XOR operation.
      • Lines 9–10: isinstance(obj, Test) will check whether the argument object obj is of the Test.class type or not. It then performs the bitwise logical XOR.
      • Line 12: When argument is of different type.When the argument is of a different type, it returns a value error.
        • Lines 15–18: We create two objects of the Test class, that is, a=9 and b=12. Finally, using the above created function, we perform the logical XOR.

        The NOT operator

        Below, we see an example of bitwise NOT operator's overloading:

        # Python program to demonstrate
        # operator overloading
        class Test():
        def __init__(self, value):
        self.value = value
        # magic method for NOT
        def __invert__(self):
        print("Overloaded NOT Operator")
        if isinstance(self, Test):
        return ~self.value
        else:
        raise ValueError("Must be an instance of Test class")
        # Driver's code
        if __name__ == "__main__":
        a = Test(9) # 0000 1001
        print(~a)

        Explanation

        • Lines 3–12: We create a Test class with value as a field. It has a magic method __invert__() to perform the bitwise logical NOT.
        • Lines 9–10: isinstance(obj, Test) will check whether the argument object obj is of Test.class type or not. We then perform the bitwise logical NOT.
        • Line 12: When argument is of different type.When the argument is of a different type, it returns a value error message.
          • Lines 14–16: We create an object of the Test class a. Finally, using the function we created above, we perform the logical NOT.

          Left shift <<

          Below, we see an example of the bitwise left shift (<<) operator's overloading:

          # Python program to demonstrate
          # operator overloading
          class Test():
          def __init__(self, value):
          self.value = value
          # Left shift of bits
          def __lshift__(self, obj):
          print("Overloaded LEFT SHIFT Operator")
          if isinstance(obj, Test):
          return self.value << obj.value
          else:
          raise ValueError("Must be an instance of Test class")
          # Driver's code
          if __name__ == "__main__":
          a = Test(2) # 0000 0010
          b = Test(3) # 0000 0011
          print(a << b)

          Explanation

          • Lines 3–12: We create a Test class with value as a field. It has a magic method __lshift__() to perform the bitwise left shift.
          • Lines 9–10: isinstance(obj, Test) will check whether the argument object obj is of Test.class type or not. We then perform the bitwise logical left shift.
          • Line 12: When the argument is of a different type, it returns a value error message.
            • Lines 14–17: We create two instances of the Test class types a=2 and b=3. Finally, using the function we created above, we perform the logical left shift.

            Right shift >>

            Below, we see an example of the bitwise right shift >> operator's overloading:

            # Python program to demonstrate
            # operator overloading
            class Test():
            def __init__(self, value):
            self.value = value
            # right shift
            def __rshift__(self, obj):
            print("Overloaded RIGHT SHIFT Operator")
            if isinstance(obj, Test):
            return self.value >> obj.value
            else:
            raise ValueError("Must be an instance of Test class")
            # Driver's code
            if __name__ == "__main__":
            a = Test(2) # 0000 0010
            b = Test(3) # 0000 0011
            print(a >> b)

            Explanation

            • Lines 3–12: We create a Test class that contains a single member field. It has a magic method __rshift__() to perform bitwise's right shift.
            • Lines 9–10: isinstance(obj, Test) will check whether the argument object obj is of the Test.class type or not. We then perform the bitwise logical right shift.
            • Line 12: When the argument is of a different type, it returns a value error message.
              • Lines 14–17: We create two instances of Test class types. a=2 and b=3. Finally, we use the function we created above to perform the bitwise right shift.

              Free Resources