The following introductory paragraph was generated with the help of AI.
Python is a popular programming language used by developers for various purposes, such as data analysis, web development, machine learning, and more. However, this language has a pretty low entry threshold, and without a broad understanding of the principles you may occasionally write some redundant or over-complex code.
In this article, we'll discuss some basic principles of coding in python that can help you optimize your programs' performance.
I will also provide some code examples to show these concepts.
The code in this article was generated with the help of AI
Python comes with many built-in functions and libraries that can save you time and effort when writing code. Also, built-in functions are usually more optimized by underlying C implementation calls. For example, you can use these functions instead of writing your own:
# maximum numeric
max([4, 1, 8])
# Result: 8
# minimum numeric
min([4, 1, 8])
# Result: 1
# sorted ascending list
sorted([4, 1, 8])
# Result: [1, 4, 8]
# sorted descending list
reversed([4, 1, 8])
# Result: [8, 4, 1]
# sum of a list
sum([4, 1, 8])
# Result: 13
# list of tuples where each tuple
# contains one item from each list
list(zip([4, 1, 8], ["orange", "banana", "apple"]))
# Result: [(4, 'orange'), (1, 'banana'), (8, 'apple')]
# tuples of the form (index, value)
# for each item in a list
list(enumerate(["orange", "banana", "apple"]))
# Result: [(0, 'orange'), (1, 'banana'), (2, 'apple')]
# iterator containing only the items
# in the iterable for which the function
# returns True
list(filter(lambda x: x % 2 == 0, [4, 1, 8]))
# Result: [4, 8]
# applies the function to each item
# in the iterable
list(map(lambda x: x ** 2, [4, 1, 8]))
# Result: [16, 1, 64]
# apply a function to each item in
# an iterable and reduce the iterable
# to a single cumulative value
from functools import reduce
reduce(lambda x, y: x * y, [4, 1, 8])
# Result: 32
# returns True if all items in the iterable are true
all(char.isupper() for char in "HELLO WORLD")
# Result: True
# returns True if any item in the iterable is true
any(char.isdigit() for char in "hello 123 world")
# Result: True
Similarly, instead of writing your own function to calculate statistical values you can use functions from the statistics library:
import statistics
# Example 1: Using mean()
numbers = [1, 2, 3, 4, 5]
mean = statistics.mean(numbers)
print(mean)
# Output: 3
# Example 2: Using median()
numbers = [1, 2, 3, 4, 5]
median = statistics.median(numbers)
print(median)
# Output: 3
# Example 3: Using mode()
numbers = [1, 2, 3, 4, 4, 5, 5, 5]
mode = statistics.mode(numbers)
print(mode)
# Output: 5
Using built-in functions and libraries can be faster and more reliable than writing your own code, especially for performing routine tasks.
It’s a good idea to overview the task and try to optimize the code whenever possible.
# Define a storage to keep previous results
results = {}
# Define a function to perform a calculation
def calculate(x):
if x in results:
# Return the result from the dictionary if it has already been calculated
return results[x]
else:
# Perform the calculation if it hasn't been done before
result = x ** 2
# Put the result in the dictionary
results[x] = result
return result
# Use the function to calculate the squares of some numbers
print(calculate(5)) # Output: 25
print(calculate(3)) # Output: 9
print(calculate(5)) # Output: 25 (retrieved from the storage)
Function calls in Python are relatively expensive in comparison to for example C. That's why you need to try to avoid nested function calls when possible.
# Instead of this
def func1(i):
return i + 1
def func2(n):
x = 0
for i in range(n):
x = func1(x)
# It is better to do this
def func(n):
x = 0
for i in range(n):
x = x + 1
Avoiding unnecessary computations can save you time and improve your program's performance, especially for large data sets.
List comprehensions are a concise and efficient way to create lists or dictionaries in Python. They allow you to write a single line of code that generates a new list/dict based on an existing object. When to use it:
# Creating a new list
squares = [i * i for i in range(6)]
# Result: [0, 1, 4, 9, 16, 25]
# Filtering an existing list
squares = [0, 1, 4, 9, 16, 25]
squares = [i for i in squares if i > 10]
# Result: [16, 25]
When not to use it:
# Long or complicated computation (reduced readability)
squares = [0, 1, 4, 9, 16, 25]
squares = [i for i in squares if i > 0 and (i % 2 == 0 or i % 5 == 0)]
# Result: [4, 16, 25]
List comprehensions can be faster and more readable than for loops, especially for simple operations.
Generators are a type of iterable, similar to lists or tuples, but they generate values on-the-fly instead of storing them in memory. They can be more memory-efficient than lists, especially for creating an infinite or large sequence (especially with heavy computations)
# Generator for squares
squares = (i ** 2 for i in range(1000000))
next(squares)
# Result: 0
next(squares)
# Result: 1
next(squares)
# Result: 4
Python offers a wide range of built-in data structures, such as lists, tuples, sets, and dictionaries. Each data structure has its own strengths and weaknesses, and choosing the right one for the task can make a big difference in performance. For example, if you need to perform set operations, such as union or intersection, use a set instead of a list. Sets are optimized for these operations and can be much faster than lists.
Here's an example:
# Using a set to perform set operations
set1 = {1, 2, 3}
set2 = {2, 3, 4}
union = set1.union(set2)
intersection = set1.intersection(set2)
print(union) # Output: {1, 2, 3, 4}
print(intersection) # Output: {2, 3}