如何获得当前所在类的名称?
例子:
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),我不能使用
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__ |
编辑:
正如
编辑:是的,你可以;但是您必须作弊:当前运行的类名出现在调用堆栈上,
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中实现的
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__) |
将有效打印
但是,无法获得正在定义的类的实际句柄。
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__) |