Python Tricks Every Developer Should Know
This article will demonstrate Python tricks that can streamline your code and make your development process smoother.
1. Utilizing Mighty Ellipsis (...) for Placeholder Values
The ellipsis (...) in Python is a built-in constant, primarily used as a placeholder. It's often seen in slicing notation for multi-dimensional arrays or when defining stubs for functions or classes that are to be implemented later.
def calculate_area(length, width):
...
# Example Usage (incomplete for demonstration)
result = calculate_area(5, 10)
print(result)
def process_data(data: list[int, str, ...]) -> None:
# Function implementation
pass
import numpy as np
# Create a multidimensional array
arr = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]], [[13, 14, 15], [16, 17, 18]]])
# Slice along the first axis
sliced_arr_1 = arr[0, ...] # Equivalent to arr[0, :, :]
print("Sliced along the first axis:\n", sliced_arr_1)
# Slice along the second axis
sliced_arr_2 = arr[:, 1, ...] # Equivalent to arr[:, 1, :]
print("\nSliced along the second axis:\n", sliced_arr_2)
# Slice along the third axis
sliced_arr_3 = arr[..., 1] # Equivalent to arr[:, :, 1]
print("\nSliced along the third axis:\n", sliced_arr_3)
# output
Sliced along the first axis:
[[1 2 3]
[4 5 6]]
Sliced along the second axis:
[[ 4 5 6]
[10 11 12]
[16 17 18]]
Sliced along the third axis:
[[ 2 5]
[ 8 11]
[14 17]]
2. Self-Documenting Magic with F-strings
F-strings, introduced in Python 3.6, allow for concise string formatting.
population = 1000000
formatted_population = f"{population:,}"
print(formatted_population)
# Output: 1,000,000
When dealing with floating-point numbers, it's often helpful to control the precision of the decimals. F-strings allow us to specify the desired precision with ease
pi = 3.14159265359
formatted_pi = f"{pi:.2f}"
print(formatted_pi)
# Output: 3.14
# Pad with spaces to the left (left-aligned)
padded_left = f"Python{' ':<10}Programming"
print(padded_left)
# Output: Python Programming
# Pad with spaces to the center (center-aligned)
padded_center = f"Python{' ':^10}Programming"
print(padded_center)
# Output: Python Programming
# Pad with spaces to the right (right-aligned)
padded_right = f"Python{' ':>10}Programming"
print(padded_right)
# Output: Python Programming
# Pad with dashes to the left
padded_left_dash = f"Python{'-':-<15}Programming"
print(padded_left_dash)
# Output: Python--------Programming
# Pad with dashes to the right
padded_right_dash = f"Python{'-':->15}Programming"
print(padded_right_dash)
# Output: PythonProgramming--------
Using = in f-strings makes it easier to create self-documenting code by embedding variable names directly into the string.
name = "Alice"
age = 30
# Output: name='Alice' is age=30 years old
print(f"{name=} is {age=} years old")
3. Walrus Operator (:=)
The walrus operator assigns values to variables as part of an expression. It's particularly useful in while loops and comprehensions to avoid redundant calculations.
# Without walrus operator
data = [1, 2, 3, 4, 5]
if len(data) > 3:
print(len(data))
# With walrus operator
if (n := len(data)) > 3:
print(n)
4. Mastering Combinations with itertools.product() for Cartesian Product Computation
As developers, we often find ourselves grappling with nested loops, searching for ways to streamline our code and enhance readability "itertools.product()" eliminates the need for nested for loops.
Consider the following scenario: You have two lists, colors and shapes, and you want to generate all possible combinations of elements from these lists. Traditionally, you might resort to nested loops to achieve this
# Original code with nested for loop
colors = ['red', 'green', 'blue']
shapes = ['circle', 'square']
combinations = []
for color in colors:
for shape in shapes:
combinations.append((color, shape))
print(combinations)
While this code gets the job done, it lacks elegance and readability. Nested loops can quickly become cumbersome, especially when dealing with multiple iterables.
Enter itertools.product()—your ticket to simplicity and efficiency. With just a single line of code, you can achieve the same result without the hassle of nested loops:
from itertools import product
colors = ['red', 'green', 'blue']
shapes = ['circle', 'square']
combinations = list(product(colors, shapes))
print(combinations)
By leveraging itertools.product(), we eliminate the need for nested loops, resulting in cleaner and more concise code.
领英推荐
5. NamedTuple for Lightweight Data Structures
We often encounter scenarios where we need lightweight data structures to represent simple objects. Enter namedtuple—a versatile tool that combines the benefits of tuples and dictionaries, offering a clean and efficient solution for managing structured data.
Advantages of Namedtuples:
6. "|" Operator for Dictionary Union
Merging dictionaries in Python involves using methods like update() or dictionary comprehension. However, Python 3.9 introduced a more concise and intuitive syntax using the | operator, reminiscent of set operations.
# Define two dictionaries
dict1 = {'a': 1, 'b': 2}
dict2 = {'b': 3, 'c': 4}
# Merge dictionaries using the | operator
merged_dict = dict1 | dict2
print(merged_dict)
# Output: {'a': 1, 'b': 3, 'c': 4}
the | operator merges dict1 and dict2, prioritizing values from dict2 in case of overlapping keys. The result is a merged dictionary containing all key-value pairs from both dictionaries.
7. Power of Single Dispatch Function and Single Dispatch Method in Python
We're constantly seeking ways to improve code organization, readability, and maintainability. Enter the single dispatch and single dispatch method—a dynamic duo of Python features that empower developers to write more flexible and extensible code.
Single dispatch is a feature introduced in Python 3.4 as part of the functools module. It allows developers to define a generic function that performs different actions based on the type of its input arguments. This enables polymorphic behavior, similar to method overloading in other languages.
from functools import singledispatch
@singledispatch
def process_data(data):
raise NotImplementedError("Unsupported data type")
@process_data.register(int)
def _(data):
print("Processing integer:", data)
@process_data.register(str)
def _(data):
print("Processing string:", data)
# Usage
process_data(10) # Output: Processing integer: 10
process_data("hello") # Output: Processing string: hello
In this example, we define a generic function process_data() using @singledispatch, and then register specialized implementations for different data types using @process_data.register(). This allows the function to behave differently based on the type of its input argument.
The single dispatch method is a similar concept to single dispatch, but it's applied to methods within classes. This allows developers to define different behavior for methods based on the type of the first argument (typically self).
from functools import singledispatchmethod
class MyClass:
@singledispatchmethod
def process(self, data):
raise NotImplementedError("Unsupported data type")
@process.register(int)
def _(self, data):
print("Processing integer:", data)
@process.register(str)
def _(self, data):
print("Processing string:", data)
# Usage
obj = MyClass()
obj.process(10) # Output: Processing integer: 10
obj.process("hello") # Output: Processing string: hello
We define a class MyClass with a method process() decorated with @singledispatchmethod. We then register specialized implementations for different data types using @process.register().
8. Potential of functools.partial in Python
We're shining a light on functools.partial—a lesser-known yet incredibly powerful tool that can simplify your code. functools.partial is a function provided by Python's functools module. It allows you to create partial function objects, which are essentially functions with some of their arguments pre-filled. This enables you to create new functions based on existing ones, with specific arguments already set.
from functools import partial
# Define a function
def greet(name, greeting):
return f"{greeting}, {name}!"
# Create a partial function
say_hello = partial(greet, greeting="Hello")
# Usage
print(say_hello("Alice")) # Output: Hello, Alice!
print(say_hello("Bob")) # Output: Hello, Bob!
we define a greet() function that takes two arguments: name and greeting. We then use functools.partial() to create a new function say_hello with the greeting argument pre-filled with "Hello".
The true power of functools.partial lies in its versatility and flexibility. Here are a few tricks you can try:
9. Python's Unconventional Function Parameter Syntax
Python's function parameter syntax offers a wide range of possibilities beyond the traditional positional and keyword arguments. Among these are the use of / and * separators, which provide unique ways to define function signatures.
def greet(name, /, greeting="Hello"):
return f"{greeting}, {name}!"
# Test the function
print(greet("Alice")) # Output: Hello, Alice!
print(greet("Bob", "Hi")) # Output: Hi, Bob!
In this example, the name parameter is positional-only, while greeting is a keyword parameter. The / separator indicates that name must be passed by position.
def calculate(a, b, *, operation="add"):
if operation == "add":
return a + b
elif operation == "subtract":
return a - b
else:
raise ValueError("Invalid operation")
# Test the function
# Output: 8 (default operation is 'add')
print(calculate(5, 3))
print(calculate(5, 3, operation="subtract")) # Output: 2
In this example, a and b are positional parameters, while operation is a keyword-only parameter. The * separator indicates that all parameters after it must be passed by keyword.
Conclusion
I hope this was clear and easy to understand.
Senior Software Developer | Python Expert | Skilled in Cloud Finance Operations, Data Processing & Cloud Platforms (AWS, Azure, GCP) | B1 Visa Holder | Quick Learner
8 个月good one Suresh Chandra Sekar