如何在Python类定义阶段获取类名并创建类内Logger?
Great question! When you're in the body of a class definition (the code that runs when the class statement is executed), the class object itself hasn't been created yet—so there's no built-in __class_name__ attribute you can access directly. But there are a couple of clean ways to get the class name without hardcoding it.
Method 1: Use the inspect module to grab the class name from the call stack
You can leverage Python's inspect module to peek at the execution context and extract the class name while the class is being defined. Here's how:
import inspect class Foo: # Get the current execution frame current_frame = inspect.currentframe() # The parent frame holds the context of the class definition class_name = current_frame.f_back.f_code.co_name print(f'Creating class {class_name}') # Clean up the frame to avoid memory leaks del current_frame # Example: Initialize your Logger with the class name # logger = Logger(class_name)
When you run this, it will output:
Creating class Foo
Notes:
- Always delete the frame after using it to prevent memory leaks from lingering frame references.
- This works for top-level classes; if you're dealing with nested classes, you might need to adjust the frame traversal (e.g.,
f_back.f_back), but that's rare for most use cases.
Method 2: Use a metaclass for reusable class-wide setup
If you want to add a Logger (or any class-specific setup) to multiple classes without repeating code, a metaclass is a better approach. Metaclasses control how classes are created, so they get access to the class name before the class is fully initialized:
# Assume this is your Logger class class Logger: def __init__(self, class_name): self.class_name = class_name print(f'Logger initialized for {class_name}') class LoggerMeta(type): def __new__(cls, class_name, bases, namespace): # Add a Logger instance to the class namespace using the class name namespace['logger'] = Logger(class_name) # Create and return the new class return super().__new__(cls, class_name, bases, namespace) # Use the metaclass in your classes class Foo(metaclass=LoggerMeta): pass class Bar(metaclass=LoggerMeta): pass
Running this will output:
Logger initialized for Foo
Logger initialized for Bar
Why this works:
The metaclass's __new__ method is called right after the class body is executed but before the class object is assigned to its name. It receives the class name as the first parameter, so you can use it to set up your Logger (or any other class-specific resources) automatically.
Bonus: If you need the class name inside methods
If your Logger is going to be used inside class/instance methods (not during class definition), you can simply use:
- In instance methods:
self.__class__.__name__ - In class methods:
cls.__name__
Example:
class Foo: def some_method(self): print(f'Running method in {self.__class__.__name__}') @classmethod def class_method(cls): print(f'Running class method in {cls.__name__}')
内容的提问来源于stack exchange,提问作者federicober

