是否可以在类定义主体中获取类名?
例如,
class Foo():
x = magic() # x should now be 'Foo'
我知道我可以使用类方法在类主体之外静态地执行此操作:
class Bar():
@classmethod
def magic(cls):
print cls.__name__
Bar.magic()
但这不是我想要的,我想要类主体中的类名
好的 - 又多了一个解决方案 - 这个实际上并没有那么复杂!
import traceback
def magic():
return traceback.extract_stack()[-2][2]
class Something(object):
print magic()
它将打印出“Something”。我不确定提取的堆栈格式是否以任何方式标准化,但它适用于 python 2.6(以及 2.7 和 3.1)
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
这里有一个针对您的具体情况的可行解决方案,但要注意(我写它主要是为了证明确实可以做这样的事情):
无论如何,这里有代码:
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__
变量不再保存字符串(我正在尝试这个)
我不知道在 Python 2.x 中执行此操作的优雅方法 - 但它是一种解释性语言,这意味着以下几行相对简单的东西将执行您想要的操作,并且如果您确定的话,那么这将是安全的正在执行的代码:
classdef = """\
class %(classname)s(object):
x = '%(classname)s'
print x
"""
exec classdef % {'classname': 'Foo'}
foo = Foo()
print foo
现在可能是一个问题
__qualname__
class AClass:
def __init__(self):
print(f"Initializing an object of class {AClass.__qualname__}")
def __repr__(self):
return f"{AClass.__qualname__}()"
有了这个定义:
>>> ac = AClass()
Initializing an object of class 'AClass'
>>> ac
Body of AClass.fun
__qualname__
也可以应用于方法。如果在类的主体中定义了方法(或内部类),则可以获得其完全限定名称,例如
# ...
def fun(self):
print(f"Body of {AClass.fun.__qualname__}")
然后,实例化对象后:
ac = AClass()
ac.fun()
给出:Body of AClass.fun
。
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
属性获取类名。