【问题标题】:Get name of current class?获取当前班级的名称?
【发布时间】:2011-10-20 01:37:16
【问题描述】:

如何获取我目前所在班级的名称?

例子:

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

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

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

【问题讨论】:

    标签: python class


    【解决方案1】:

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

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

    用法:

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

    【讨论】:

    • 为什么这不是公认的答案?编辑:好的 OP 的范围不是内部的,它在类级别。
    • @KomodoDave,因为这是错误的,即使在方法范围内也是如此。当您从子类调用 getName 时,它将输出子类名称。如果你真的想要你正在使用的课程,那么它会变得很棘手。
    • @KenetJervet 你的意思是当你从 parent 类调用getName 时,它会输出子类名?好的,请指出这一点。
    • 在 OO 术语中,解决方案(即使 getName() 方法恰好在超类中定义,也返回实际的运行时子类名称)是正确的。
    【解决方案2】:

    在类的主体中,类名尚未定义,因此不可用。你不能简单地输入班级的名字吗?也许您需要详细说明问题,以便我们为您找到解决方案。

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

    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'
    

    【讨论】:

    • 澄清我要做什么:我需要创建并初始化一个类变量“输入”,在方法之外。我有一堆小类,每个类都必须使用它们的类名作为参数调用“get_input”。我试图概括这一点,所以我不必去每个班级(大约有 100 个)并输入班级名称。
    • 好的,我已经用一个应该有帮助的元类更新了我的答案。
    • InputAssigningMetaclass 中的super 行中的MyType 指的是什么?
    【解决方案3】:

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

    对于顶级函数和类,__qualname__ 属性等于__name__ 属性。对于嵌套类、方法和嵌套函数,__qualname__ 属性包含从模块顶层到对象的虚线路径。

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

    class Foo:
        print(__qualname__)
    

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

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

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

    【讨论】:

    • 这是最好的答案!
    【解决方案4】:

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

    cls_name = self.__class__.__name__
    

    编辑:

    正如Ned Batchelder 所说,这在类体中不起作用,但在方法中会起作用。

    【讨论】:

    • 类体中如何引用类?我需要将当前类传递给另一个类。
    【解决方案5】:

    编辑:是的,你可以;但你必须作弊:当前运行的类名存在于调用堆栈上,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'
    >>> 
    

    【讨论】:

      【解决方案6】:

      @Yuval Adam 使用@property 回答

      class Foo():
          @property
          def name(self):
              return self.__class__.__name__
      
      f = Foo()
      f.name  # will give 'Foo'
      
      

      【讨论】:

        【解决方案7】:
        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()
        

        【讨论】:

          【解决方案8】:

          我想,应该是这样的:

              class foo():
                  input = get_input(__qualname__)
          

          【讨论】:

            猜你喜欢
            • 2011-05-26
            • 1970-01-01
            • 2013-01-25
            • 2017-06-02
            • 1970-01-01
            • 1970-01-01
            • 2012-12-30
            相关资源
            最近更新 更多