是否可以在类定义的主体中获取类名?
例如,
class Foo():
x = magic() # x should now be 'Foo'
我知道我可以使用类方法在类体外静态地执行此操作:
class Bar():
@classmethod
def magic(cls):
print cls.__name__
Bar.magic()
然而,这不是我想要的,我想要类体
中的类名答案 0 :(得分:6)
好的 - 还有一个解决方案 - 这个实际上并不复杂!
import traceback
def magic():
return traceback.extract_stack()[-2][2]
class Something(object):
print magic()
它将打印出“Something”。我不确定提取的堆栈格式是否以任何方式标准化,但它适用于python 2.6(以及2.7和3.1)
答案 1 :(得分:4)
AFAIK,在类定义被“执行”之前,类对象不可用,因此在类定义期间无法获取它。
如果您需要类名以供以后使用,但在类定义期间不使用它(例如计算其他字段名称或某些此类事物),那么您仍然可以使用类装饰器自动执行该过程。
def classname ( field ):
def decorator ( klass ):
setattr(klass, field, klass.__name__)
return klass
return decorator
(警告:未经测试。)
通过这个定义,你可以得到类似的东西:
@classname(field='x')
class Foo:
pass
你会得到包含类名的字段x
,如:
print Foo.x
答案 2 :(得分:1)
我不知道在Python 2.x中执行此操作的优雅方法 - 但它是一种解释性语言,这意味着沿着以下行的相对简单的事情将做你想要的,如果你是安全的话会是安全的确定正在执行的代码:
classdef = """\
class %(classname)s(object):
x = '%(classname)s'
print x
"""
exec classdef % {'classname': 'Foo'}
foo = Foo()
print foo
答案 3 :(得分:1)
在这里,你有一个适合你特定案例的工作解决方案,但要注意(我写的主要是为了证明确实可以这样做):
无论如何,这里有代码:
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__
编辑: https://gist.github.com/1085475 - 您有一个允许在方法执行期间使用__clsname__
的版本;没有多大意义,因为self.__class__.__name__
是一种更好的方法,而__clsname__
变量不再包含字符串(我很开心尝试这个)
答案 4 :(得分:-2)
class Bar():
@classmethod
def magic(cls):
return cls.__name__
@property
def x(self):
return self.magic()
def y(self):
return self.x
>>> a = Bar()
>>> a.x
'Bar'
>>> a.y()
'Bar'
这样您就可以使用x
作为属性,至少在任何实例和静态方法中都是如此。在类方法中,您无论如何都可以从cls
属性获取类名。