xbe.at

Python / Python for ML and AI

Using Asterisk to Improve Code Readability and Functionality in Python

4 min read, 14 sections

Contents
  1. Using the Asterisk (\) in Python
  2. Variable Length Arguments in Functions
  3. Extended Iterable Unpacking
  4. Multiplying Sequences
  5. Keyword-Only Arguments
  6. Ignoring Values
  7. Merging Dictionaries
  8. Unpacking Arguments
  9. Matrix Transposition
  10. Passing Keyword Arguments
  11. Combining \args and \\kwargs
  12. Type Hinting with \args and \\kwargs
  13. Unpacking in Function Definitions
  14. Additional Resources

Using the Asterisk (*) in Python

The asterisk (*) symbol in Python is a powerful and versatile operator that can enhance code readability and functionality. It has multiple uses beyond simple multiplication, including variable-length arguments, extended iterable unpacking, sequence multiplication, and more. This presentation will explore these applications with practical examples.

# The asterisk (*) has many uses in Python
print("Let's explore them!")

Variable Length Arguments in Functions

The asterisk allows functions to accept any number of positional arguments. This flexibility is useful when you don't know in advance how many arguments will be passed to a function.

def sum_all(*args):
    total = 0
    for num in args:
        total += num
    return total

result = sum_all(1, 2, 3, 4, 5)
print(f"Sum of all numbers: {result}")  # Output: Sum of all numbers: 15

Extended Iterable Unpacking

The asterisk can be used to unpack iterables into separate variables, capturing remaining elements in a list.

first, *middle, last = range(1, 6)
print(f"First: {first}, Middle: {middle}, Last: {last}")
# Output: First: 1, Middle: [2, 3, 4], Last: 5

*beginning, end = "Python"
print(f"Beginning: {beginning}, End: {end}")
# Output: Beginning: ['P', 'y', 't', 'h', 'o'], End: n

Multiplying Sequences

The asterisk can be used to repeat sequences, creating new sequences with repeated elements.

repeated_list = [1, 2, 3] * 3
print(f"Repeated list: {repeated_list}")
# Output: Repeated list: [1, 2, 3, 1, 2, 3, 1, 2, 3]

repeated_string = "abc" * 3
print(f"Repeated string: {repeated_string}")
# Output: Repeated string: abcabcabc

Keyword-Only Arguments

The asterisk can be used to specify keyword-only arguments in function definitions, enforcing the use of keyword arguments for certain parameters.

def greet(name, *, greeting="Hello"):
    return f"{greeting}, {name}!"

print(greet("Alice"))  # Output: Hello, Alice!
print(greet("Bob", greeting="Hi"))  # Output: Hi, Bob!
# print(greet("Charlie", "Hey"))  # This would raise a TypeError

Ignoring Values

The asterisk can be used as a placeholder to ignore certain values when unpacking iterables.

data = ["Alice", "Smith", 30, "Engineer"]
name, *_, occupation = data
print(f"Name: {name}, Occupation: {occupation}")
# Output: Name: Alice, Occupation: Engineer

for _ in range(3):
    print("This line will be printed 3 times")

Merging Dictionaries

The double asterisk (**) can be used to merge dictionaries in a concise manner.

dict1 = {"a": 1, "b": 2}
dict2 = {"c": 3, "d": 4}
merged = {**dict1, **dict2}
print(f"Merged dictionary: {merged}")
# Output: Merged dictionary: {'a': 1, 'b': 2, 'c': 3, 'd': 4}

Unpacking Arguments

The asterisk can be used to unpack iterables as arguments when calling functions.

def vector_add(x, y, z):
    return [x + 1, y + 1, z + 1]

coords = [1, 2, 3]
result = vector_add(*coords)
print(f"Result: {result}")  # Output: Result: [2, 3, 4]

Matrix Transposition

The asterisk can be used in list comprehensions to transpose a matrix efficiently.

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
transposed = [list(row) for row in zip(*matrix)]
print(f"Transposed matrix: {transposed}")
# Output: Transposed matrix: [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

Passing Keyword Arguments

The double asterisk (**) can be used to pass keyword arguments from a dictionary to a function.

def create_profile(name, age, city):
    return f"{name}, {age} years old, from {city}"

user_data = {"name": "Alice", "age": 30, "city": "New York"}
profile = create_profile(**user_data)
print(profile)  # Output: Alice, 30 years old, from New York

Combining *args and **kwargs

The asterisk and double asterisk can be used together to create highly flexible functions.

def flexible_function(*args, **kwargs):
    print(f"Positional arguments: {args}")
    print(f"Keyword arguments: {kwargs}")

flexible_function(1, 2, 3, name="Alice", age=30)
# Output:
# Positional arguments: (1, 2, 3)
# Keyword arguments: {'name': 'Alice', 'age': 30}

Type Hinting with *args and **kwargs

The asterisk can be used in type hints to indicate variable-length arguments and keyword arguments.

from typing import Any

def process_data(*args: int, **kwargs: Any) -> None:
    for arg in args:
        print(f"Processing integer: {arg}")
    for key, value in kwargs.items():
        print(f"Keyword argument: {key} = {value}")

process_data(1, 2, 3, name="Alice", active=True)

Unpacking in Function Definitions

The asterisk can be used to force keyword arguments in function definitions.

def safe_division(numerator, denominator, *, ignore_zero_division=False):
    try:
        return numerator / denominator
    except ZeroDivisionError:
        if ignore_zero_division:
            return float('inf')
        raise

print(safe_division(1, 0, ignore_zero_division=True))  # Output: inf
# print(safe_division(1, 0, True))  # This would raise a TypeError

Additional Resources

For more information on using the asterisk in Python, consider exploring these resources:

  1. Python Documentation: https://docs.python.org/3/tutorial/controlflow.html#unpacking-argument-lists
  2. PEP 3102 - Keyword-Only Arguments: https://www.python.org/dev/peps/pep-3102/
  3. PEP 448 - Additional Unpacking Generalizations: https://www.python.org/dev/peps/pep-0448/

These resources provide in-depth explanations and examples of the concepts covered in this presentation.

More in Python for ML and AI

  1. Using isinstance() for Cleaner More Efficient Python Code8 min

    The type() function returns the exact class type of an object without considering inheritance relationships. It performs strict type checking by comparing...

  2. Unlocking the Power of Type Hinting in Python8 min

    Type hinting is a feature in Python that allows developers to specify the expected data types of variables, function parameters, and return values. It...

  3. Using Self Type Annotations in Python10 min

    The Self type annotation in Python provides a way to indicate that a method returns an instance of its own class. This pattern is particularly useful in...

  4. Unlocking Python's Power with Custom Import Hooks8 min

    Python's import system is a powerful mechanism that allows you to organize and reuse code. It's the foundation for modular programming in Python, enabling...

  5. Vector Embedding in Python Representing Semantic Relationships10 min

    Vector embedding is a technique used to represent discrete objects as continuous vectors in a high-dimensional space. This method allows us to capture...

  6. Universal Continuous Knowledge Graph Builder in Python10 min

    A Universal Continuous Knowledge Graph Builder is a system that dynamically constructs and updates a knowledge graph from various data sources in real-time....