ZetCode

Python pow Function

Last modified April 11, 2025

This comprehensive guide explores Python's pow function, which calculates powers and modular exponents. We'll cover basic exponents, modular arithmetic, performance considerations, and practical examples.

Basic Definitions

The pow function returns base raised to the power of exponent. It can optionally take a third argument for modular exponentiation.

Key characteristics: works with integers, floats, and complex numbers. With three arguments, it's more efficient than (x**y) % z. Always returns float for negative exponents.

Basic Exponentiation

Here's simple usage showing how pow calculates basic exponents with different numeric types and edge cases.

basic_pow.py
# Integer exponents
print(pow(2, 3))     # 8
print(pow(10, 0))    # 1

# Float exponents
print(pow(4, 0.5))   # 2.0 (square root)
print(pow(2, -1))    # 0.5

# Edge cases
print(pow(0, 0))     # 1 (math convention)

This example shows pow with positive, negative, and fractional exponents. Note that any number to power 0 returns 1, including 0^0.

Negative exponents return float results. Fractional exponents calculate roots (0.5 gives square root). The function handles edge cases gracefully.

Modular Exponentiation

The three-argument form efficiently computes (base^exp) % mod. This is crucial for cryptography and number theory applications.

modular.py
# Simple modular arithmetic
print(pow(2, 3, 5))    # 8 % 5 = 3
print(pow(5, 2, 3))    # 25 % 3 = 1

# Cryptographic example
prime = 17
base = 3
private_key = 5
public_key = pow(base, private_key, prime)
print(public_key)      # 3^5 mod 17 = 5

# Large numbers
print(pow(1234567, 2345678, 333))  # 271

The three-argument form is optimized for large numbers, making it essential for cryptographic algorithms like RSA and Diffie-Hellman.

It's more efficient than computing exponentiation then modulo separately, especially with large numbers, as it prevents intermediate value overflow.

Custom Objects with __pow__

You can make custom objects work with pow by implementing __pow__ and optionally __rpow__ special methods.

custom_pow.py
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __pow__(self, exp):
        return (self.x**exp + self.y**exp)**(1/exp)
    
    def __repr__(self):
        return f"Vector({self.x}, {self.y})"

v = Vector(3, 4)
print(pow(v, 2))  # 5.0 (Euclidean norm)
print(pow(v, 3))  # 4.497941445275415 (3-norm)

The Vector class implements __pow__ to calculate p-norms. When we call pow on a Vector instance, Python uses this method.

This pattern is useful for mathematical classes where exponentiation has a meaningful interpretation (vectors, matrices, etc.).

Performance Comparison

This example compares pow performance with the ** operator and math.pow for different use cases.

performance.py
import timeit
import math

def test_pow():
    return pow(2, 100)

def test_operator():
    return 2 ** 100

def test_math_pow():
    return math.pow(2, 100)

def test_mod_pow():
    return pow(123456, 789012, 333)

def test_mod_manual():
    return (123456 ** 789012) % 333

print("pow():", timeit.timeit(test_pow, number=10000))
print("** operator:", timeit.timeit(test_operator, number=10000))
print("math.pow:", timeit.timeit(test_math_pow, number=10000))
print("mod pow:", timeit.timeit(test_mod_pow, number=100))
print("mod manual:", timeit.timeit(test_mod_manual, number=100))

pow and ** are generally comparable for integer exponents, while math.pow is optimized for floating-point operations.

For modular exponentiation, the three-argument pow is vastly superior to manual computation, especially with large numbers.

Error Handling

The pow function raises various exceptions for invalid inputs. This example demonstrates proper error handling.

errors.py
try:
    print(pow("2", "3"))
except TypeError as e:
    print(f"TypeError: {e}")

try:
    print(pow(2, 3, 0))  # mod 0 is invalid
except ValueError as e:
    print(f"ValueError: {e}")

class NoPow:
    pass

try:
    print(pow(NoPow(), 2))
except TypeError as e:
    print(f"TypeError: {e}")

These examples show pow's error behavior. Strings raise TypeError, mod 0 raises ValueError, and objects without __pow__ raise TypeError.

To make a class work with pow, implement __pow__ as shown in the custom objects example.

Best Practices

Source References

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Python tutorials.