Python中类体内的类名

12 投票
5 回答
2950 浏览
提问于 2025-04-16 21:38

在类的定义内部,能不能获取到类的名字呢?

比如说,

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

我知道我可以在类的外面,用一个类方法静态地获取这个名字:

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

Bar.magic()

但是我想要的不是这个,我想在类的内部获取类的名字。

5 个回答

2

这里有一个适合你特定情况的解决方案,但要注意(我写这个主要是为了展示确实可以做到这样的事情):

  • 你不应该使用它
  • 它非常具体
  • 有很多限制
  • 我只是玩得开心
  • 这有点像黑魔法
  • 可能不适合你的使用场景
  • 它不是线程安全的
  • 我是不是已经说过你不应该使用它了?

无论如何,这里是代码:

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

据我所知,类对象在类定义“执行”之前是不可用的,所以在定义类的时候无法获取它。

如果你需要在之后使用类名,但在定义类的时候不想用它(比如说用来计算其他字段名之类的),那么你可以通过使用类装饰器来自动化这个过程。

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
8

好的,我再提供一个解决方案,这个其实并不复杂!

import traceback

def magic():
   return traceback.extract_stack()[-2][2]

class Something(object):
   print magic()

它会输出“Something”。我不太确定提取的堆栈格式是否有标准,但它在python 2.6(还有2.7和3.1)中是有效的。

撰写回答