获取当前课程的名称?


102

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

例:

def get_input(class_name):
    [do things]
    return class_name_result

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

由于我要与(vistrails)交互的程序的性质,我不能使用__init__()initialize input

Answers:


158

obj.__class__.__name__ 将获得任何对象名称,因此您可以执行以下操作:

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

用法:

>>> c = Clazz()
>>> c.getName()
'Clazz'

1
为什么这不是公认的答案?编辑:确定OP的范围不在内部,它是在类级别。
KomodoDave 2014年

6
@KomodoDave,因为即使在方法范围内,这也是错误的。getName从子类调用时,它将输出子类名称。如果您真的想要您正在使用的类,那么它将变得很棘手。
Kenet Jervet

@KenetJervet您的意思是,当您getName类调用时,它将输出子类名称?可以指出这一点。
KomodoDave

5
但是,在OO术语中,解决方案(即使getName()方法恰好在超类中定义,也要返回实际的运行时子类名称)是正确的。
sxc731 '16

22

在类的主体内,类名尚未定义,因此不可用。您不能简单地输入班级名称吗?也许您需要更多地谈论该问题,以便我们为您找到解决方案。

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

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'

为了阐明我要做什么:我需要在method之外创建并初始化一个类变量'input' 。我有一堆小类,每个小类都必须使用其类名作为参数来调用“ get_input”。我试图对此进行概括,所以我不必去每个班级(大约有100个班级)并输入班级名称。
乔纳森·金斯堡

好的,我已经使用应该有用的元类更新了答案。
Ned Batchelder

1
是什么MyTypesuperInputAssigningMetaclass指什么?
A.Wan 2015年

16

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

cls_name = self.__class__.__name__

编辑:

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


11

引入了PEP 3155__qualname__,它是在Python 3.3中实现的。

对于顶级函数和类,该__qualname__属性等于该__name__属性。对于嵌套类,方法和嵌套函数,该__qualname__属性包含一个虚线路径,该虚线路径从模块顶层通向该对象。

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

class Foo:
    print(__qualname__)

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

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

>>> class Foo:
...     print('Foo' in globals())
... 
False

7

编辑:是的,您可以;但您必须作弊:调用堆栈中存在当前正在运行的类名,并且该traceback模块允许您访问堆栈。

>>> 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'

但是,我不会这样做。我最初的答案仍然是我自己的解决方案。原始答案:

可能最简单的解决方案是使用装饰器,该装饰器与Ned涉及元类的答案类似,但功能较弱(装饰器具有黑魔法的能力,但元类却具有古老的,神秘的黑魔法的能力)

>>> 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'
>>> 

1
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

我认为应该是这样的:

    class foo():
        input = get_input(__qualname__)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.