DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Python Software Development: Unlocking the Power
  • What to Know About Python and Why Its the Most Popular Today
  • Start Coding With Google Cloud Workstations
  • Beyond ChatGPT, AI Reasoning 2.0: Engineering AI Models With Human-Like Reasoning

Trending

  • A Guide to Developing Large Language Models Part 1: Pretraining
  • Fixing Common Oracle Database Problems
  • Unlocking AI Coding Assistants Part 1: Real-World Use Cases
  • Internal Developer Portals: Modern DevOps's Missing Piece
  1. DZone
  2. Coding
  3. Languages
  4. Best Ways to Write Clean and Quality Python Code

Best Ways to Write Clean and Quality Python Code

The article below will provide insights that can be helpful in your day-to-day coding and improve the quality of your Python code.

By 
Dhaval Patolia user avatar
Dhaval Patolia
·
Mar. 26, 25 · Analysis
Likes (5)
Comment
Save
Tweet
Share
4.7K Views

Join the DZone community and get the full member experience.

Join For Free

When considering whether to use classes in Python code, it's important to weigh the benefits and contexts where they are most appropriate. Classes are a key feature of object-oriented programming (OOP) and can provide clear advantages in terms of organization, reusability, and encapsulation. However, not every problem requires OOP.

When to Use Classes

Encapsulation and Abstraction

  • Encapsulation. Classes allow you to bundle data (attributes) and methods (functions) that operate on the data into a single unit. This helps in keeping related data and behaviors together.
  • Abstraction. Classes can hide the complex implementation details and expose only the necessary parts through public methods.

Reusability

  • Reusable components. Classes can be represented multiple times, allowing you to create reusable components that can be used in different parts of your application.

Inheritance and Polymorphism

  • Inheritance. Classes allow you to create new classes based on existing ones, reusing the code and reducing redundancy.
  • Polymorphism. Classes enable you to define methods in such a way that they can be used interchangeably, improving flexibility and integration.

Stateful Function Using Classes

Using a class is a more explicit way to manage state. Use classes when the stateful function requires multiple methods.

Python
 
class Counter
	def__init__(self):
    	self.count =0
      
	def increment(self):
    	self.count =1
        return self.count
      
# Create a counter instance
counter1 = Counter()
print(counter1.increment()) #Output:1
print(counter1.increment()) #Output:2
print(counter1.increment()) #Output:3

# Create another counter instance
counter2 = Counter()
print(counter2.increment()) #Output:1
print(counter2.increment()) #Output:2


When Not to Use Classes

Simple Scripts and Small Programs

For small scripts and simple programs, using functions without classes can keep the code straightforward and easy to understand.

Stateless Functions

If your functions do not need to maintain any state and only perform operations based on input arguments, using plain functions is often more appropriate.

Best Practices for Using Classes

Naming Conventions

  • Use CamelCase for class names.
  • Use descriptive names that convey the purpose of the class.

Single Responsibility Principle

Ensure each class has a single responsibility or purpose. This makes them easier to understand and maintain.

Best Practices for Writing Functions

Function Length and Complexity

  • The functions should be small, with the focus on a single item.
  • Aim for functions to be no longer than 50 lines; if they are longer, consider refactoring.

Pure Functions

Write pure functions where possible. Its output is determined only by its input and has no side effects. It always produces the same output for the same input. It has several benefits, including easier testing and debugging, as well as better code maintainability and reusability. 

They also facilitate parallel and concurrent programming since they don't rely on the shared state or mutable data.

Python
 
def add(a,b):
  """Add two numbers."""
  return a + b
#Usage
result = add(4,2)
print(result) # Output:6


Impure Functions

It relies on external state and produces side effects, which makes its behavior unpredictable.

Python
 
total = 0
def add_to_total(value):
  """Add a value to the global total"""
  global total
  total += value
  
#Usage:
add_to_total(4)
print(total) #Output: 4

add_to_total(2)
print(total) #Output: 6


Documentation

  • Use docstrings to document the purpose and behavior of functions
  • Include type hints to specify the expected input and output types

Static Methods

It is used when you want a method to be associated with a class rather than an instance of the class. Below are a few scenarios.

  • Grouping utility functions. It is a group of related functions that logically belong to a class but don't depend on instance attributes or methods.
  • Code organization. It helps in organizing the code by grouping related functions with in a class, even if they don't operate on instance-level data.
  • Encapsulation. It clearly communicates that they are related to the class, not to any specific instance, which can enhance code readability.

DateUtils.py

Python
 
from datetime import datetime
class Dateutils:
  @staticmethod
  def is_valid_date(date_str, format="%Y-%m-%d"):
    """
    checks if a string is a valid date in the specified format.
    Args:
    date_str(Str): the date strig to validate.
    format(str, optional): the date format to use (default "%Y-%m-%d").
    Returns:
    bool: true if the date is valid, false otherwise.
    """
    
    try:
      datetime.strptime(date_str, format)
      return True
    except ValueError:
      return False
    
    @staticmethod
    def get_days_difference(date1_str, date2_str, format ="%Y-%m-%d"):
       """
       calculates number of days between two dates
       Args:
        date1_str(Str): the first date string.
        date2_str(Str): the second date string.
        format(str, optional): the date format to use (default "%Y-%m-%d").
       Returns:
        int: the number of days between two dates.
        """
        
        date1 = datetime.strptime(date1_str, format)
        date2 = datetime.strptime(date2_str, format)
        return abs(date2 - date1).days) # abs() is used for non negative difference
      
      #usage
      valid_date = DateUtils.is_valid_date("2025-03-07")
      print(f"Is'2025-03-07' is a valid date? {valid_date}") #output:True
      
      days_diff = DateUtils.get_days_difference("2025-02-01","2025-03-01")
      print(f"Days between '2025-02-26' and '2025-03-01': {days_diff}"
        


Logger

It's a built-in logging module that is a flexible and powerful system for managing application logs. It is essential for diagnosing issues and monitoring application behavior. 

The RotatingFileHandler is a powerful tool for managing log files. It allows you to create log files that automatically rotate when they reach a certain size.

log_base_config.py

Python
 
import logging
from logging.handlers import RotatingFileHandler

def setup_logging():
  #create logger
  logger = logging.getLogger()
  logger.setLevel(logging.INFO)
  
  #create a rotating file handler
  rotating_handler = RotatingFileHandler('example.log', maxBytes=1024, backupcount =30)
  rotating_handler.setLevel(logging.INFO)
  
  #create a formatter and add it to the handler
  formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
  rotating_handler.setFormatter(formatter)
  
  #add rotating file handler to the logger
  logger.addHandler(rotating_handler)


logger_impl.py

Python
 
import logging
from log_base_config import setup_loggimg

setup_logging()
logger = logging.getLogger("logger_example")

def call_logger(numerator:int,denominator:int):
  logger.info("call_logger(): start")
  #log some messages
  for i in range(32):
    logger.info(f'This is a message {i}')
  try:
    result = numerator / denominator
    logger.info("Division successful: %d / %d = %f", numerator, denominator, result)
    return result
  except ZeroDivisionError:
    logger.error("Failed to perform division due to a zero division error.")
    return None
  logger.info("call_logger(): end")
if __name__ == "__main__":
  call_logger(12,0)
    


Do Not Consume Exception

It is catching an exception without taking appropriate action such as logging the error or raising the exception again. This can make debugging difficult because the program fails silently. Instead you should handle exception in a way that provides useful information and allows the application to either recover or fail gracefully.

Here's how you can properly handle exceptions without consuming them:

  • Ensure the exception details are logged.
  • Provide user-friendly feedback or take corrective actions.
  • If appropriate, raise the exception again after logging it.

Below is an example showing how to properly handle and log a ZeroDivisionError without consuming the exception.

Python
 
import logging
from log_base_config import setup_loggimg

setup_logging()
logger = logging.getLogger("logger_example")

def divide_numbers(numerator, denominator):
  try:
    result = numerator / denominator
    logger.info("Division successful: %d / %d = %f", numerator, denominator, result)
    return result
  except ZeroDivisionError as e:
    logger.error("Division by zero error: %d / %d", numerator, denominator)
    logger.exception("Exception details:")
    #raise the exception again after logging
    raise
 # test the function
num = 10
denon = 0
  try
    logger.info("Attempting to divide %d by %d", num, denom)
    result = divide_number(num, denom)
  except ZeroDivisionError:
    logger.error("Failed to perform division due to a zero division error.")
   


Conclusion

By following these techniques, one can ensure that exceptions are handled transparently, aiding in debugging and maintaining robust application behavior.

Object-oriented programming Encapsulation (networking) Python (language)

Opinions expressed by DZone contributors are their own.

Related

  • Python Software Development: Unlocking the Power
  • What to Know About Python and Why Its the Most Popular Today
  • Start Coding With Google Cloud Workstations
  • Beyond ChatGPT, AI Reasoning 2.0: Engineering AI Models With Human-Like Reasoning

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!