So i have this problem, i want to get the name of a python class in this way:
class TestClass():
myName = (get class name here automatically)
saveDirectory = os.path.join(saveDir, myName) # so i can save it in unique location
def __init__(self):
pass # do something
However, it seems that __class__.__name__
doesn't actually exist as of yet at the time when myName
is created. So i have been forced to put that into the __init__()
function, like this:
class TestClass():
def __init__(self):
self.myName = self.__class__.__name__
saveDirectory = os.path.join(saveDir, self.myName) # so i can save it in unique location
pass # do something
But this has a big problem, because I cannot get the name of the class until I instantiate the class, I instend to create a few gigabytes of data for each instance of the class to be saved in the saveDirectory, so it can be re-used later. So I don't actually want to do go ahead with my current solution.
Is there anyway to get the class name as I have intended? Or am I just dreaming?
EDIT:
Thanks guys for your great suggestions. I am going to spend a little bit of time taking a look at Metaclasses. Otherwise, I will probably create a dictionary globally, and have references to these instantiated classes instead.
Since python 3.3, you can use the
__qualname__
variable:I guess what you're doing is not possible, because the class doesn't even exist when you do:
myName = (get class name here automatically)
But soon after the class has been interpreted you can pass the class object to some other function to do the job for you.
The only way to actually do what you are trying to during the class definition is to use a metaclass:
Or on Python 3.x:
This is definitely less clear than just using the following:
Just use a method?
Or you could just have a class attribute indicating the save directory; less magic is usually a good thing. Plus you could change the name of the class later without breaking your storage.
Also, what? Gigabytes?!
During class interpretation, there is no "there" there yet. So, yes, what your initial example shows is not possible. But please explain why this would need to be known before the class even technically exists?
Barring a good answer to that outstanding question, one is left with trying to get the class' name from:
Beyond that, please edit the question and add some details that explain why your initial attempt needs to work the way you want, before instantiation and yet internal to the class definition, while your 2nd example is problematic. Also, how does saveDir get passed/come from? (A global outside of the class?) Please show some code showing how you intend to use what you'd like to work. There may be a way to redesign to get there from here, in effect if not literally.
Other than the metaclass in F J's answer, I can think of two other ways. I'll start with the nicer looking one. You don't need to use a metaclass; sometimes a descriptor is perfectly adequate.
The other way, if you really need the class name from inside the class body (unlikely), you can snoop on the call stack. The class name, as it appears in source, is on the code object being executed by the class definition:
Of the ones presented so far, only this last one allws you to use the name, as a string, from inside the class body, Unfortunately, this doesn't work in all versions of python, notably IronPython does not implementent the call stack introspection as it's not available in the DLR.
There's a way to get it without introspecting the stack, portably. It's similar to the answer provided by F J, using a metaclass, but instead uses the
__prepare__
feature available in Python 3: