This article discusses key criteria for developing Python functions, focusing on code reusability, complexity management, and testability.
In Python, you can either use a predefined function/method or write a user-defined function/method. In this discussion, provide at least three criteria that would be used to develop an appropriate method of your choice and the rationale behind selecting these criteria. Then give an example of your method declaration and return type.
The three criteria that I consider when developing my functions/methods are as follows:
- Code reusability: When a block of code needs to be repeated multiple times in a program, the block of code is a good candidate to be modularized into a reusable function. This promotes DRY (Don’t Repeat Yourself) code, a principal in software development whose goal is to reduce repetition (Schafer, 2015). DRY.
- The rationale behind Reusable functions is to make the code more modular, readable, and maintainable. Changes only need to be made in one place.
- Task complexity: If a task is made of many steps (code blocks), wrapping the task’s steps in well-named functions makes the task more modular and hides complexity.
- The rationale is to reduce the tasks’ readable complexity by hiding the details. In other words, the goal is to separate the “what” from the “how” making the code more understandable, readable, and maintainable. This is very useful for tasks with many steps and very complex logic.
- Code testability: Encapsuling code blocks in functions with clear inputs and outputs makes testing large programs easier to test.
- The rationale is that isolating code into functions with clear inputs and outputs enhances the program’s robustness and maintainability by facilitating easier testing of the codebase.
Considering these three criteria is key to creating a professional and high-quality codebase which, in the long run, saves time and reduces frustration not only for you but also for your ‘coding teammates.’This is particularly true when it comes to refactoring the code. “Refactoring, or code refactoring in full, is a systematic process of amending previously built source code, without introducing new functionalities or altering the fundamental workings of the subject software.” (Slingerland, 2023)
Some of the actions that software development teams commonly take during refactoring include:
- Reducing the size of the code
- Restructuring confusing code into simpler code
- Cleaning up code to make it tidier
- Removing redundant, unused code and comments
- Doing away with unnecessary repetitions
- Combining similar code
- Creating reusable code
- Breaking up long functions into simpler, manageable bits (Slingerland, 2023)
Example:Here is a code example without functions and a code example with functions.The following program filters prime numbers from a list, and then checks if the square of the prime number are less than 50.
functions:
num_lst = [2, 3, 4, 5, 6, 7, 8, 9, 10]
squared_primes_less_than_50 = []
for n in num_lst:
# Check if n is prime
if n > 1:
is_prime = True
for i in range(2, int(n**0.5) + 1):
if n % i == 0:
is_prime = False
break
if is_prime:
# Calculate square
square = n**2
# Check if square is less than 50
if square < 50:
squared_primes_less_than_50.append(square)
print(squared_primes_less_than_50)
With functions:
def is_prime(n: int) -> bool:
"""
Check if a number is prime.
:param n: Integer to check for primality
:return: Boolean indicating if the number is prime
"""
if n <= 1:
return False
for i in range(2, int(n**0.5) + 1):
if n % i == 0:
return False
return True
def filter_primes(num_lst: list[int]) -> list[int]:
"""
Filter prime numbers from a list.
:param num_lst: List of integers to filter
:return: List of prime numbers from the input list
"""
return [n for n in num_lst if is_prime(n)]
def square_numbers(num_lst: list[int]) -> list[int]:
"""
Square each number in a list.
:param num_lst: List of integers to square
:return: List of squared integers
"""
return [n**2 for n in num_lst]
def squares_less_than(num_lst: list[int], threshold: int) -> list[int]:
"""
Filter numbers less than a specified threshold from a list.
:param num_lst: List of integers to filter
:param threshold: Threshold value for filtering
:return: List of numbers from the input list
that are less than the threshold
"""
return [n for n in num_lst if n < threshold]
# --- Execute the program
def main() -> None:
"""
Main function to execute the program logic.
:param None:
:return: None
"""
numbers = [2, 3, 4, 5, 6, 7, 8, 9, 10]
primes = filter_primes(numbers)
squared_primes = square_numbers(primes)
result = squares_less_than(squared_primes, 50)
print(result)
# --- Execute the program
if __name__ == "__main__":
main()
Please see the functions’ docstrings and hints for information about the return types.
In summary, by applying the principles of reusability, complexity management, and testability, you can create a robust and scalable codebase that is easier to refactor and extend. This not only improves code quality but also makes maintenance and collaboration more efficient.
References:
Schafer, C. (2015, June 16). Programming terms: Dry (don’t repeat yourself). YouTube. https://www.youtube.com/watch?v=IGH4-ZhfVDk&t=7s
Slingerland, C. (2023, December 5)._ What is refactoring? 5 techniques you can use to improve your software_. CloudZero. https://www.cloudzero.com/blog/refactoring-techniques/
Originally published at Key Criteria for Developing Python Functions - Medium on August 19, 2024.
Top comments (0)