Python class name in class

Is it possible to get the class name inside the body of the class definition?

For example,

class Foo(): x = magic() # x should now be 'Foo' 

I know that I can do this statically outside the class body using the class method:

 class Bar(): @classmethod def magic(cls): print cls.__name__ Bar.magic() 

However, this is not what I want, I want the class name in the body body

+8
python metaprogramming
source share
5 answers

Well - one more solution turned out - in fact it is not so difficult!

 import traceback def magic(): return traceback.extract_stack()[-2][2] class Something(object): print magic() 

It will display "Something." I'm not sure if the dedicated stack format is standardized in any way, but it works for python 2.6 (and 2.7 and 3.1)

+6
source share

AFAIK, the class object is unavailable until the class definition is “completed”, so it cannot be obtained during class definition.

If you need a class name for later use, but not to use it during class definition (for example, to compute other field names or some such thing), you can automate the process using the class decorator.

 def classname ( field ): def decorator ( klass ): setattr(klass, field, klass.__name__) return klass return decorator 

(Caution: not verified.)

With this definition, you can get something like:

 @classname(field='x') class Foo: pass 

and you get a field x with the class name in it, for example:

 print Foo.x 
+4
source share

I don’t know an elegant way to do this in Python 2.x, but it is an interpreted language that means something relatively simple in the following lines will do what you want and it would be safe if you made sure that it executes the code:

 classdef = """\ class %(classname)s(object): x = '%(classname)s' print x """ exec classdef % {'classname': 'Foo'} foo = Foo() print foo 
+1
source share

Here you have a working solution for your specific case, but be careful (I wrote mainly to demonstrate that you can really do something like this):

  • You should not use it
  • This is very specific.
  • He has many limitations.
  • I was just having fun
  • This is black magic.
  • It may not work for your use.
  • It is not thread safe
  • I already said that you should not use it?

Anyway, here you have the code:

 import inspect def NameAwareClassType(): frameInfo = inspect.getouterframes(inspect.currentframe())[1] codeContext = frameInfo[4][0] className = codeContext.split(' ', 1)[1].split('(', 1)[0] class ClassNameGlobalRemoverType(type): def __new__(mcs, name, bases, dict): if name == className: del globals()['__clsname__'] return type.__new__(mcs, name, bases, dict) class NameAwareClass(object): __metaclass__ = ClassNameGlobalRemoverType globals()['__clsname__'] = className return NameAwareClass class A(NameAwareClassType()): print __clsname__ def __init__(self): pass print __clsname__ 

Edit: https://gist.github.com/1085475 - there is a version that allows you to use __clsname__ during the execution of the method; doesn't make much sense since self.__class__.__name__ is the best approach and the __clsname__ variable no longer contains a string (I am happy to experiment with this)

+1
source share
 class Bar(): @classmethod def magic(cls): return cls.__name__ @property def x(self): return self.magic() def y(self): return self.x >>> a = Bar() >>> ax 'Bar' >>> ay() 'Bar' 

This way you can use x as an attribute, at least in any instance and static methods. In class methods, you can simply get the class name from the cls attribute.

-2
source share

All Articles