Going Beyond the
Basics: Rarely Used Python
Operators and Functions

Going Beyond the Basics: Rarely Used Python Operators and Functions

Python has so many inbuilt functions you can never learn them completely.

Introduction

I am a self-taught python developer for more than 3 years now and yet I'm constantly surprised by the new things I learn every day. Each day I find a new operator or function which makes life so much easier. Many operators and functions are inbuilt and knowing them makes a huge difference. It's not possible to learn them all but at least you can get familiar with them. So here's my cheat sheet for some rarely used in python3.

Operators

We can directly say that operator is a symbol or a set of symbols which is used to represent an action or a process. Operators are used to manipulate values and perform calculations, comparisons, and other operations in a program. All most all programming languages have the same set of operators like

  • Arithmetic operators ( + , - , * , / )

  • Comparison operators ( == , != , < , > )

  • Logical operators ( AND , OR , NOT )

  • Assignment operators ( = )

  • Bitwise operators ( bitwise AND , bitwise OR , bitwise NOT )

These are simple operators that can be found in many programming languages.

But we are not here to talk about them, let's get right into the topic which is some rarely used operators in python. If you are already familiar with those, it suggests that you possess strong development skills.

Floor Division ( // )

In contrast to standard division, floor division returns the largest possible integer. This number is either less than or equal to the outcome of the usual division. We can do the same in python by using the operator //.

# Floor division
print(5 // 2)
# Output: 2

In python, there is no ceiling equivalent operator. But you can use upside-down floor division.

def ceildiv(a, b):
    return -(a // -b)

print(ceildiv(5, 2)

Walrus Operator ( := )

Python 3.8 introduces the walrus operator that lets you assign a value to a variable as part of an expression. You can use it in situations where you want to evaluate an expression and use the result later. By reducing duplication and improving logic flow, the walrus operator makes your code more concise and readable. You don't need to declare the variable first and then assign it, you can directly do that.

a = [1, 2, 3, 4]
if (n := len(a)) > 3:
    print(f"List is too long ({n} elements, expected <= 3)")

Matrix Multiplication Operator ( @ )

Matrix Multiplication Operator was introduced in Python 3.5 and it is used to multiply two-dimensional arrays in python. It's not available to use with the standard data structures of python rather it was specifically introduced for the numpy arrays. Numpy is a library specifically dealing with the operations of arrays or lists.

import numpy as np
A = np.array([[1, 2], [3, 4], [5, 6]])
B = np.array([[7, 8], [9, 10]])
result = A @ B
print(result)

But you can do the same on standard not directly but you can convert it to numpy array and then multiply using the Operator.

import numpy as np
A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
arr = np.array(A)
B = [[10, 11, 12], [13, 14, 15], [16, 17, 18]]
arr2 = np.array(B)
result = arr @ arr2
print(result)

Set-like Operators

Python's "set-like operators" are operations like union, intersection, difference, and the symmetric difference that behave like set operations but can also be used with other sequence types.

  • | (union): returns a new set that is absent of duplicates and contains every element from both sets (or other sequence types).

  • & (intersection): returns a new set that only includes the components that are shared by the two sets (or other sequence types).

  • - (difference): returns a new set that only includes the items from the first set (or another sequence type) that aren't present in the second set.

  • ^ (symmetric difference): returns a new set that only includes the items that are present in one of the two sets (or other sequence types), but not both.

list1 = [1, 2, 3]
list2 = [2, 3, 4]

# Union
result_union = list(set(list1) | set(list2))
print(result_union)
# Output: [1, 2, 3, 4]

# Intersection
result_intersection = list(set(list1) & set(list2))
print(result_intersection)
# Output: [2, 3]

# Difference
result_difference = list(set(list1) - set(list2))
print(result_difference)
# Output: [1]

# Symmetric difference
result_symmetric_difference = list(set(list1) ^ set(list2))
print(result_symmetric_difference)
# Output: [1, 4]

In addition to sets, these operators can be applied to other sequence classes, such as lists, tuples, and strings. The returned output will be of the same type as the first argument when applied to non-set sequence types.

Functions

You can think of a function as a block of code that performs a specific task. Functions enable you to break your code into smaller, more modular pieces, making it easier to read, write, and maintain. Input arguments can be passed into functions, and then they can perform calculations or operations on them.

Many inbuilt functions are available in python and many may know the standard ones like

• len() - returns the number of items in an object such as a string, list, or tuple.

• input() - allows the user to input values from the keyboard and returns the entered value as a string.

• range() - a function that generates a sequence of numbers between the given start, stop and step values.

• sum() - returns the sum of all elements in an iterable such as a list or a tuple.

These are just some of the examples, the list may go far further. But for now, let's go deep down into rarely used python built-in functions.

sorted()

In Python, you can sort a list with list.sort(). Keep in mind that this method modifies the original list in place, so the list gets sorted directly. Instead, you can use the sorted() function to get a sorted copy of the list while maintaining the integrity of the original list. The original list is not changed by this method; instead, it returns a fresh, sorted list.

arr = [5, 7, 3, 6, 2, 9, 1, 4, 8]
sort_arr = sorted(arr)
print(arr)
print(sort_arr)
# Output
# [5, 7, 3, 6, 2, 9, 1, 4, 8]
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

slice()

To specify how to slice a sequence, use a slice object. You can define the beginning and ending points of the slicing. Additionally, you can specify the step, allowing you to, for example, slice only the remaining items.

my_list = [1, 2, 3, 4, 5]
my_slice = slice(1, 4, 2)
print(my_list[my_slice])  # Output: [2, 4]

divmod()

The divmod() is a method in python that takes two numbers as arguments and returns a pair of numbers consisting of their quotient and remainder. This is better when you have both remainder and quotient needed for something.

a = 6
b = 4
print(divmod(a,b))
# Output: (1, 2)

reversed()

The method returns an iterator that accesses the given sequence in reverse order. list.reverse() also does the same task but the original list is modified directly, and no new list is created. And with reversed() it does not modify the original list but instead returns a new list with the elements in reverse order.

my_list = [1, 2, 3, 4, 5]
reversed_list = list(reversed(my_list))
print(reversed_list)
# Output: [5, 4, 3, 2, 1]

callable()

callable() is an internal function that, if the given object may be used as a function, returns True; otherwise, it returns False.

def foo():
    pass

print(callable(foo))
# Output: True

x = 5
print(callable(x))
# Output: False

class Bar:
    def __call__(self):
        pass

b = Bar()
print(callable(b))
# Output: True

lst = [1, 2, 3]
print(callable(lst))
# Output: False

setattr() and getattr()

The value of an attribute on an object is set with the setattr() function. Three parameters are required: the object whose attribute is to be set, the attribute's name as a string, and the value to set.

class Person:
    pass

p = Person()
setattr(p, 'name', 'John')
print(p.name)
# Output: John

The value of an attribute of an object is retrieved by the getattr() function. It requires two arguments: the object whose attribute is to be obtained and the attribute's name as a string. AttributeError is raised if the attribute is missing.

class Person:
    name = 'John'

p = Person()
print(getattr(p, 'name'))
# Output: John

vars()

A built-in function called vars() gives the value of an object's __dict__ attribute. It gives back a dictionary that contains the object's (local) symbol table, or all the attributes that were defined for the object.

class MyClass:
    def __init__(self, a, b):
        self.a = a
        self.b = b
obj = MyClass(1, 2)
print(vars(obj))
# output: {'a': 1, 'b': 2}

filter()

It is possible to filter components from an iterable (like a list) based on a function by using the built-in function filter(). The filter() method accepts two arguments: an iterable and a function that returns either True or False (such as a list). Only the components for which the function returns True are included in the resulting iterable after being applied to each element in the iterable.

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

def is_even(n):
    return n % 2 == 0

even_numbers = list(filter(is_even, numbers))

print(even_numbers)
# Output: [2, 4, 6, 8, 10]

next()

To get the next item from an iterator, use the built-in Python method next(). The next element in the sequence is returned when next() is invoked on an iterator. The StopIteration exception is raised if the sequence contains no additional components. To iterate over an iterator's components one by one, use the next() function in a loop.

my_list = [1, 2, 3, 4, 5]
my_iterator = iter(my_list)

print(next(my_iterator)) # Output: 1
print(next(my_iterator)) # Output: 2
print(next(my_iterator)) # Output: 3
print(next(my_iterator)) # Output: 4
print(next(my_iterator)) # Output: 5

# This will raise the StopIteration exception
print(next(my_iterator)) # Output: StopIteration

hash()

Python comes with a built-in function called hash() that gives an object's hash value. The hash value, which is a distinct integer that symbolises the object, can be used for several things, including comparing objects for equality and storing them in hash tables.

# hash a string
my_string = "hello world"
hash_value = hash(my_string)
print(hash_value)
# Output: -7156188717690076749

zip()

Python's zip() method accepts iterable as input and produces an iterator of tuples as a result. The matching elements from each iterable are contained in each tuple.

numbers = [1, 2, 3]
colors = ['red', 'green', 'blue']
result = zip(numbers, colors)
print(list(result))
# Output: [(1, 'red'), (2, 'green'), (3, 'blue')]

locals() and globals()

Built-in functions called locals() and globals() return dictionaries with the current local and global symbol tables, respectively.

x = 10  # global variable

def my_func():
    y = 20  # local variable
    print("locals:", locals())
    print("globals:", globals())

my_func()
# Output:
# locals: {'y': 20}
# globals: {..., 'x': 10, 'my_func': <function my_func at 0x7f5de5b72560>}

dis()

Python bytecodes can be disassembled using the dis module. It is primarily used to comprehend how the Python interpreter runs your code. A list of instructions containing the disassembled code is written to the console.

import dis

def my_func(a, b):
    c = a + b
    return c

dis.dis(my_func)

Output:

  4           0 LOAD_FAST                0 (a)
              2 LOAD_FAST                1 (b)
              4 BINARY_ADD
              6 STORE_FAST               2 (c)

  5           8 LOAD_FAST                2 (c)
             10 RETURN_VALUE

eval()

eval() is a Python function that returns the result of evaluating a string as a Python expression. The syntax for the eval() function is:

eval(expression, globals=None, locals=None)

where expression is the string to be evaluated as a Python expression and globals and locals are optional dictionaries defining the global and local variable namespaces.

Here's an example of how to use eval():

x = 10
y = 20
expr = "x + y"
result = eval(expr)
print(result)

Conclusion

There are several built-in operators and functions in Python, some of which are well-known while others are less well-known. In addition to performing numerous tasks like sorting, filtering, and data transformation, these functions and operators can assist developers in writing more concise and effective code. Certain lesser-known Python operators and functions, like slice(), dis(), reduce(), and chain(), as well as some frequently used ones, likesorted(), filter(), and len(), have been addressed in this blog. Even though it's impossible to go over every function and operator in Python, the examples we've given should aid developers in bettering their knowledge and comprehension of the language.

Did you find this article valuable?

Support Akash R Chandran by becoming a sponsor. Any amount is appreciated!