I have a number of classes with code like this. Each __init__
starts a thread and a logger with the name of the class. How do I get the name of the current class in its own definition, as a string, inside __init__
? Note that self
may not be an instance of the current class, so the following is not quite foolproof.
from threading import Thread
import logging
def myClassName(myclass):
myclass._class_name = myclass.__name__
return myclass
@myClassName
class SomeClass(object):
def __init__(self):
class_name = type(self)._class_name
print "My class name in __init__ is", class_name
self.thread = Thread(name=class_name)
self.logger = logging.getLogger(class_name)
Update:
To clarify:
To get the class name of an instance in Python: Use the type() function and __name__ to get the type or class of the Object/Instance. Using the combination of the __class__ and __name__ to get the type or class of the Object/Instance.
Use the __init__() method to initialize the object's attributes. The __init__() doesn't create an object but is automatically called after the object is created.
The __init__ method is the Python equivalent of the C++ constructor in an object-oriented approach. The __init__ function is called every time an object is created from a class. The __init__ method lets the class initialize the object's attributes and serves no other purpose. It is only used within classes.
Understanding Python super() with __init__() methods It is known as a constructor in Object-Oriented terminology. This method when called, allows the class to initialize the attributes of the class. The super() function allows us to avoid using the base class name explicitly.
You can retrieve the name of the class of an an object thus:
obj.__class__.__name__
Example:
class SomeClass(object):
def __init__(self):
print("I am a %s"%self.__class__.__name__)
class Derived(SomeClass):
pass
x = SomeClass()
y = Derived()
Result:
$ python x.py
I am a SomeClass
I am a Derived
In Python 3 this is pretty straight forward, we can use the __class__
cell variable to get the current class.
In Python 2 we can achieve something similar by injecting class's name in functions globals scope using a metaclass and later cleaning it up.
from functools import wraps
from types import FunctionType
def decorate(func, class_name):
@wraps(func)
def wrapper(*args, **kwargs):
sentinel = object()
actual_value = func.__globals__.get('__class__', sentinel)
func.__globals__['__class__'] = class_name
try:
result = func(*args, **kwargs)
finally:
if actual_value is sentinel:
del func.__globals__['__class__']
else:
func.__globals__['__class__'] = actual_value
return result
return wrapper
class Meta(type):
def __new__(cls, name, bases, attrs):
for k, v in attrs.items():
if isinstance(v, FunctionType):
attrs[k] = decorate(v, name)
return type.__new__(cls, name, bases, attrs)
class A:
__metaclass__ = Meta
def func(self):
print(__class__)
print('Inside A')
class B(A):
def func(self):
print(__class__)
print('Inside B')
super(B, self).func()
B().func()
Output:
B
Inside B
A
Inside A
To get the __class__
variable as the class object itself we can make few changes:
def decorate(func, cls):
@wraps(func)
def wrapper(*args, **kwargs):
sentinel = object()
actual_value = func.__globals__.get('__class__', sentinel)
func.__globals__['__class__'] = cls
try:
result = func(*args, **kwargs)
finally:
if actual_value is sentinel:
del func.__globals__['__class__']
else:
func.__globals__['__class__'] = actual_value
return result
return wrapper
class Meta(type):
def __new__(cls, name, bases, attrs):
cls = type.__new__(cls, name, bases, attrs)
for k, v in attrs.items():
if isinstance(v, FunctionType):
setattr(cls, k, decorate(v, cls))
return cls
Now output would be:
<class '__main__.B'>
Inside B
<class '__main__.A'>
Inside A
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With