#   # Mastering Python Operations (Part 3)

In our preceding blog posts, we delved into the concepts of Relational and Logical operators. Throughout three blogs, we meticulously discussed various operators. To gain an in-depth understanding of these operators, we kindly encourage you to explore our earlier blog entries.

With this foundation, we now present the concluding blog in our series on operators. We invite you to seamlessly transition from our previous discussions and join us in further exploring the intricacies of operators in this final installment. Your continued interest and engagement are greatly appreciated.

## Bitwise Operators

When operating on individual bits of numeric values, bitwise operators work at the binary level. They are important in low-level programming and certain instances of data manipulation while being less often employed.

On binary representations of integers, these operators do out operations.

### Bitwise ANDOperator(&)

The bitwise AND operation is a crucial operation in computer programming, comparing binary values using the '&' sign, enabling efficient permission checks and bitwise manipulations.

### How it works

• The outcome bit is set to 1 if both of the operand's corresponding bits are 1. The outcome bit is set to 0 if any of the relevant operand bits are 0.

### Example 1

Let's look at an instance where you have a collection of data that represents various permissions and you want to utilize bitwise AND to determine whether or not a certain permission is authorized.

Let's say you have the enumerated authorization flags.

• Input: 0010

• Output: 0100

• Delete: 1000

Confirm the user's read and write permissions using binary integer representation, indicating allowed(1) or not(0).

Let's assume that the user has the following permissions: 0011

You may use the bitwise AND operation to determine whether the user has "Read" and "Write" permissions.

``````  0011 (User's permissions)
& 0010 (Write permission flag)
-----------
0010
``````

The user does have the "Write" permission, as shown by the result of 0010. They lack the "Read" permission, though, as the "Read" matching bit is set to 0.

### Bitwise OROperator(|)

Bitwise OR is a common technique in programming to efficiently manage various settings, flags, or attributes using binary representations, resulting in a compact set of options.

### How it works

• The outcome bit is set to 1 if any of the corresponding bits in the operands is 1. The outcome bit is set to 0 if both of the operands' corresponding bits are 0.

### Example 2

Let's say you have the enumerated authorization flags.

• Write: 0010

• Execute: 0100

• Delete: 1000

A user should be given "Read" and "Write" access. To combine these two flags, utilize the bitwise OR technique.

``````  0001 (Read permission flag)
| 0010 (Write permission flag)
-----------
``````

The outcome, 0011, denotes permissions with both "Read" and "Write" capabilities.

User "Read," "Write," and "Execute" permissions. You can use the bitwise OR operation

``````  0011 (Read and Write combined)
| 0100 (Execute permission flag)
-----------
0111 (Read, Write, and Execute combined)
``````

The outcome is 0111, which is the sum of the three permits.

### Bitwise XOROperator(^)

Another essential operation in computer programming that works on the individual bits of binary integers is the bitwise XOR (exclusive OR) operation. The bitwise XOR operation between two binary values is done using the symbol "^"

The bitwise XOR technique is used to toggle or flip specific bits in a binary integer.

### How it works

• The result bit is set to 1 if the matching operand bits vary (one is 0 and the other is 1).

• The outcome bit is set to 0 if the corresponding operand bits are the same (either both 0s or both 1s).

### Example 3

This example shows how to efficiently manipulate bits in programs by selectively flipping or toggling particular bits in a binary representation using the bitwise XOR function.

``````  00110110 (Original number)
^ 00100100 (Mask for toggling 3rd and 6th bits)
-----------
00010010 (Result after toggling)
``````

To toggle the third and sixth bits, create a mask with all bits set to 0, and only toggle the desired bits.

### Bitwise NOTOperator(~)

The bitwise NOT operation or bitwise complement uses the symbol '~*'.*

### How it works

In the operand, each 1-bit is converted to a 0-bit, and vice versa for each 0-bit.

### Example 4

Let's use the binary number 00101011 as an example and execute a bitwise NOT operation on it.

Original number: 11011001

Mask: 11101111 (bits 2 and 5 cleared, other bits set to 1)

``````#Original:  00101011
#Bitwise NOT: 11010100

11011001 (Original number)
-----------
11001001 (Result after clearing bits)

``````

Create a mask with desired bits set to 0, and all other bits set to 1, and perform a bitwise AND operation between the original number and the mask to clear the second and fifth bits.

### Left shiftOperator(<<)

Left shift is a bitwise operation that moves the bits of the left operand to the left by a specific number of places. It is a common optimization technique in low-level programming.

### How it works

• The right operand's number shifts each bit in the left operand, deleting any moved bits past the leftmost position and pushing zeros from the right side.

### Example 5

To multiply a binary number by a power of 2, use the left shift operation. For example, to multiply 00101010 by 4 (a power of 2), left-shift the bits by 2 positions. Then, perform a bitwise AND between the original number and mask.

``````Original:     00101010
Left Shift 2: 10101000
``````

The left shift operation results in 10101000, representing the original number multiplied by 4. It can also be used for multiplication by larger powers of 2, like multiplying by 8 (which is 2^3), you would shift the bits by 3 positions.

``````Original:     00101010
Left Shift 3: 10100000 #the left shift operation produces the number 10100000, which is the original number times eight
``````

### Right shiftOperator(>>)

The right shift operation, denoted by the symbol (>>), is a bitwise operation that moves the bits of the left operand to the right by a certain number of places.

### How it works

• The left operand of a number is shifted to the right by the number of positions specified in the right operand.

• Unsigned numbers have zeros shifted in from the left side, while signed numbers have arithmetic or logical right shifts depending on the programming language and system architecture.

### Example 6

To extract the green component from a color representation with red, green, and blue components, right-shift the color by 8 positions, discarding the least significant bits. This demonstrates the use of right-shift operations in conjunction with other bitwise operations to manipulate and extract specific fields from binary data structures.

To eliminate the least important 8 bits (the blue component), move the entire color to the right by 8 places.

``````Original Color:  RRRRRRRRGGGGGGGGBBBBBBBB
Right Shift 8:   00000000RRRRRRRRGGGGGGGG
``````

The green component is at the least significant 8 bits of the result, extracted by bitwise AND operation with mask set to 1.

``````00000000RRRRRRRRGGGGGGGG (Result after right shift)
``````

The result of the bitwise AND operation is the extracted green component of the color.

## Membership Operators

Membership operators improve efficiency in searching and filtering by determining if a specific value is present in a sequence (such as a list, tuple, or string).

• In Operator

• Not In

### IN Operator

Returns True if a value is found in the sequence

To determine if a certain value is contained in a sequence, such as a list, tuple, string, or other iterable data types, programmers frequently use the in operator. The in-operator is quite handy for searching for specific values within sequences and is commonly used for decision-making and conditional checks in programming.

### How it works

The in-operator returns True if the value on the left side of the operator is present in the sequence on the right side. The operator returns False if the value is missing from the sequence.

### Example 7

list of usernames, and you want to use the in operator to see if a certain username is present in the list.

``````# List of usernames
usernames = ["Sanjay", "Amit", "Shashank", "Jhanavi", "Preeti"]

# Check if the username exists in the list
else:
``````
``````The username 'Sanjay' exists.
``````

The result will be a list of usernames, and you want to use the in operator to see if a certain username is already in the list if you alter search_username to a username that isn't already in the list, like 'Akhila'.

``````The username 'Akhila' does not exist
``````

### Not In Operator

To detect whether a certain value is absent from a sequence, such as a list, tuple, string, or other iterable data types, use the not-in operator.

• The not-in operator returns True if the value on the left side of the operator cannot be found in the sequence on the right side.

• The operator returns False if the value is present in the sequence.

### Example 8

When building a restaurant reservation system, you have a tuple that represents the available tables. You want to be sure that you can make a reservation for a certain table.

``````# Tuple representing available tables
available_tables = ("Table 1", "Table 2", "Table 3", "Table 4", "Table 5")

# Check if a table is not available for reservation
table_to_reserve = "Table 6"
if table_to_reserve not in available_tables:
print(f"{table_to_reserve} is not available for reservation.")
else:
print(f"{table_to_reserve} is available for reservation.")
``````
``````Table 6 is not available for reservation.
``````

The not-in operation returns True, indicating that "Table 6" is not a part of the available_tables tuple and so cannot be reserved.

## IdentityOperators

Understanding identity operators is essential for understanding object-oriented programming and memory management since they provide a way to determine if two variables represent the same memory object.

When comparing two objects' memory locations, identity operators are utilized

### Is Operator

Returns True if two variables reference the same object

Python's is-operator may be used to determine whether two variables correspond to the same memory item. Instead of determining if the values of the objects are equal, it verifies the identity of each item.

### Example 9: Creating a web application's caching system

To increase speed, you should keep frequently used data in memory. You may keep cached data in a dictionary and quickly determine if a given item has already been cached by using the is operator.

``````# Dictionary to store cached data
cache = {}

def get_data_from_cache(key):
if key in cache:
print(f"Getting data for key '{key}' from cache.")
return cache[key]
else:
return None

# Simulating caching data
data = [1, 2, 3, 4]
cache["my_data"] = data

# Using the get_data_from_cache function
requested_data = get_data_from_cache("my_data")
if requested_data is data:
print("Using cached data.")
else:
print("Data not in cache. Fetching from source and caching.")
data.append(5)

requested_data = get_data_from_cache("my_data")
if requested_data is data:
print("Using cached data.")
else:
print("Data not in cache. Fetching from source and caching.")
#The is operator returns True if cached data remains unchanged,
#demonstrating object identity in practical scenarios like caching.
``````

The get_data_from_cache() function compares the returned data to the cached data using the is operator to verify object identity. If the is-operator returns True, the modified data is not reflected in the cached data. This demonstrates the is-operator usefulness in practical cases like caching.

### Is Not Operator

When determining if two variables relate to separate objects, the is not operator is frequently employed. This might help determine whether things are distinct in memory.

### Example 10

You use a messaging program and want to know if the recipient of a message has read it. The is not operator can be used to detect if a new message object, which denotes that the message has been read, differs from the original message object.

``````class Message:
self.content = content

original_message = Message("Hey there!")