python:获取当前类的名称?

如何获得当前所在类的名称?

例子:

1
2
3
4
5
6
def get_input(class_name):
    [do things]
    return class_name_result

class foo():
    input = get_input([class name goes here])

由于我与之交互的程序的性质(vistrails),我不能使用__init__()初始化input


obj.__class__.__name__将为您获取任何对象名称,因此您可以这样做:

1
2
3
class Clazz():
    def getName(self):
        return self.__class__.__name__

用法:

1
2
3
>>> c = Clazz()
>>> c.getName()
'Clazz'


在类的主体中,类名还没有定义,因此它不可用。您不能简单地输入类的名称吗?也许你需要多谈谈这个问题,以便我们能为你找到解决办法。

我将创建一个元类来为您完成这项工作。它在类创建时调用(概念上是在类的末尾:block),并可以操作正在创建的类。我还没有测试过这个:

1
2
3
4
5
6
7
8
9
10
11
12
13
class InputAssigningMetaclass(type):
    def __new__(cls, name, bases, attrs):
        cls.input = get_input(name)
        return super(MyType, cls).__new__(cls, name, bases, newattrs)

class MyBaseFoo(object):
    __metaclass__ = InputAssigningMetaclass

class foo(MyBaseFoo):
    # etc, no need to create 'input'

class foo2(MyBaseFoo):
    # etc, no need to create 'input'


你可以通过类的私有属性来访问它:

1
cls_name = self.__class__.__name__

编辑:

正如Ned Batcheler所述,这在类主体中不起作用,但在方法中会起作用。


编辑:是的,你可以;但是您必须作弊:当前运行的类名出现在调用堆栈上,traceback模块允许您访问堆栈。

1
2
3
4
5
6
7
8
9
10
11
>>> import traceback
>>> def get_input(class_name):
...     return class_name.encode('rot13')
...
>>> class foo(object):
...      _name = traceback.extract_stack()[-1][2]
...     input = get_input(_name)
...
>>>
>>> foo.input
'sbb'

然而,我不会这么做;我最初的答案仍然是我自己偏爱的解决方案。最初的回答:

可能最简单的解决方案是使用decorator,它类似于Ned对元类的回答,但是功能不那么强大(decorator可以使用黑魔法,但是元类可以使用古老的神秘的黑魔法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> def get_input(class_name):
...     return class_name.encode('rot13')
...
>>> def inputize(cls):
...     cls.input = get_input(cls.__name__)
...     return cls
...
>>> @inputize
... class foo(object):
...     pass
...
>>> foo.input
'sbb'
>>>

PEP 3155引入了在Python 3.3中实现的__qualname__

For top-level functions and classes, the __qualname__ attribute is equal to the __name__ attribute. For nested classes, methods, and nested functions, the __qualname__ attribute contains a dotted path leading to the object from the module top-level.

它可以从类或函数的定义中访问,例如:

1
2
class Foo:
    print(__qualname__)

将有效打印Foo。您将获得完全限定的名称(不包括模块的名称),因此您可能希望将其拆分为.字符。

但是,无法获得正在定义的类的实际句柄。

1
2
3
4
>>> class Foo:
...     print('Foo' in globals())
...
False

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import sys

def class_meta(frame):
    class_context = '__module__' in frame.f_locals
    assert class_context, 'Frame is not a class context'

    module_name = frame.f_locals['__module__']
    class_name = frame.f_code.co_name
    return module_name, class_name

def print_class_path():
    print('%s.%s' % class_meta(sys._getframe(1)))

class MyClass(object):
    print_class_path()


我认为应该是这样的:

1
2
    class foo():
        input = get_input(__qualname__)