Back to blog

How to Get Class Names in Python – Tutorial

author avatar

Yelyzaveta Nechytailo

2025-03-253 min read
Share

In Python, accessing class names is essential for debugging complex applications, implementing robust logging systems, and working with dynamic class creation. Whether you're developing introspection tools or handling metaprogramming scenarios, understanding how to retrieve and utilize class names provides powerful capabilities for your applications. 

In this tutorial, let’s explore different methods to get class names in Python, from simple methods to advanced techniques.

Methods to get class names in Python

Python offers several methods to obtain class names, each with specific use cases and advantages. Below, we go through each approach with examples.

Using class.name

The most straightforward method for retrieving a class name is through the name attribute, which is available on all class objects. See the following example:

class UserProfile:
    def __init__(self, username):
        self.username = username

# Get name directly from class
print(UserProfile.__name__)  # Output: UserProfile

# Get name from an instance
user = UserProfile("johndoe")
print(user.__class__.__name__)  # Output: UserProfile

This approach is ideal for simple logging and debugging scenarios where you need quick access to the class name.

Using type() and name

Another popular technique that uses Python's built-in type() function to determine an object's class before accessing its name attribute. See the following example:

class Configuration:
    pass

config = Configuration()

# Get class name using type()
class_type = type(config)
class_name = class_type.__name__
print(class_name)  # Output: Configuration

# More concisely as a one-liner
print(type(config).__name__)  # Output: Configuration

The type() and name method is especially useful when working with multiple objects of unknown types or when implementing generic functions that need to handle multiple class types.

Using qualname for nested classes

When dealing with nested classes, the standard name attribute may not be able to provide the full context. The qualname attribute delivers a more complete representation of the class's location.

class Outer:
    class Inner:
        pass

print(Outer.__name__)             # Output: Outer
print(Outer.Inner.__name__)       # Output: Inner
print(Outer.Inner.__qualname__)   # Output: Outer.Inner

The qualname attribute provides the "qualified name" that includes the class's hierarchical path, making it invaluable when working with complex nested architectures.

Using the inspect module

For more advanced introspection, Python's inspect module lets you retrieve class information dynamically.

import inspect

class DataProcessor:
    def process(self):
        pass

# Get class name using inspect
processor = DataProcessor()
print(inspect.getmodule(processor).__name__)   # Output: __main__

# More commonly used approach with inspect
print(processor.__class__.__name__)           # Output: DataProcessor

The inspect module shines when you need additional metadata about classes beyond just their names, such as method signatures, inheritance hierarchies, or source code locations.

Using init_subclass()

For monitoring class creation, the __init_subclass__() hook allows you to capture class names as they're defined.

class BaseTracker:
    def __init_subclass__(cls, **kwargs):
        print(f"New subclass created: {cls.__name__}")

class EventTracker(BaseTracker):
    pass  # Output: New subclass created: EventTracker

class CustomTracker(BaseTracker):
    pass  # Output: New subclass created: CustomTracker

This method is especially useful for framework development or when implementing registries of available classes.

Getting class names for built-in types

Built-in types like int, str, and float work similarly to custom classes when retrieving their names.

number = 42
text = "Hello, World!"
decimal = 3.14

print(type(number).__name__)  # Output: int
print(type(text).__name__)    # Output: str
print(type(decimal).__name__) # Output: float

Understanding how to access these names makes it possible to create generic functions that respond differently based on the input type.

Extracting class names dynamically

When working with dynamic class creation, you might need to extract class names from various sources. This pattern often appears in serialization frameworks, ORM systems, and plugin architectures. See the below example for extracting the name of the class dynamically:

def process_objects(object_list):
    type_counts = {}
    for obj in object_list:
        class_name = obj.__class__.__name__
        type_counts[class_name] = type_counts.get(class_name, 0) + 1
    return type_counts

# Usage example
mixed_objects = [1, "text", 3.14, [1, 2, 3], {"key": "value"}]
print(process_objects(mixed_objects))  
# Output: {'int': 1, 'str': 1, 'float': 1, 'list': 1, 'dict': 1}

Best practices and common issues

When working with class names in Python, there are several best practices and common issues you should take into account. Here’s a list of best practices that will help optimize your processes:

  1. Use name for straightforward cases, as it’s simple and reliable.

  2. Use qualname for nested classes to get the full hierarchical name.

  3. Avoid hardcoding class names in your code; retrieve them dynamically instead.

  4. Be cautious with circular imports when retrieving class names across modules.

  5. Handle inheritance properly by being aware that name reflects the actual class, not its base classes.

  6. Consider namespaces when working with class names in different modules.

Some common issues to watch for include name mangling with private attributes, class reloading during development, and differences in behavior between regular and metaclasses. These issues can lead to unexpected behavior, such as inaccessible attributes, duplicate class definitions, or inconsistencies when introspecting class structures, potentially causing debugging challenges and runtime errors.

Conclusion

All in all, understanding how to get the class name in Python unlocks powerful capabilities for introspection, debugging, and dynamic programming. Whatever your use case is, having these techniques in your Python toolkit will help you develop more robust and maintainable code.

Discover more useful topics on our blog: Python web scrapingfinding elements in Selenium with Python; finding HTML elements with BeautifulSoup; scraping with Selenium and Python; using XPath Python; and more.

Frequently asked questions

Why am I getting 'main' as the class name?

If you're getting '__main__' instead of your expected Python get class name, you're likely looking at the module name rather than the class name. This commonly happens when you check name on a module object instead of a class. To fix this, ensure you're accessing Class.__name__ or object.__class__.__name__ rather than the module's name class attribute.

How do I handle classes in different modules?

For enclosing classes in different modules, you may want to access both the module name and the class name:

# For a class in another module
import datetime

now = datetime.datetime.now()
module_name = now.__class__.__module__
class_name = now.__class__.__name__
fully_qualified = f"{module_name}.{class_name}"

print(fully_qualified) # Output: datetime.datetime

This gives you the fully qualified name that uniquely identifies the class of the object within your application.

How do I get a class name without creating an instance?

You can access a class name directly from the class object without creating an instance:

class SampleClass:
pass

# No instance needed
print(SampleClass.__name__) # Output: SampleClass

This is useful when working with class registries or when you need the name for documentation or metadata purposes without the overhead of instantiation.

About the author

author avatar

Yelyzaveta Nechytailo

Senior Content Manager

Yelyzaveta Nechytailo is a Senior Content Manager at Oxylabs. After working as a writer in fashion, e-commerce, and media, she decided to switch her career path and immerse in the fascinating world of tech. And believe it or not, she absolutely loves it! On weekends, you’ll probably find Yelyzaveta enjoying a cup of matcha at a cozy coffee shop, scrolling through social media, or binge-watching investigative TV series.

All information on Oxylabs Blog is provided on an "as is" basis and for informational purposes only. We make no representation and disclaim all liability with respect to your use of any information contained on Oxylabs Blog or any third-party websites that may be linked therein. Before engaging in scraping activities of any kind you should consult your legal advisors and carefully read the particular website's terms of service or receive a scraping license.

Related articles

Get the latest news from data gathering world

I’m interested