【问题标题】:Getting the class name of an instance?获取实例的类名?
【发布时间】:2010-10-05 09:19:25
【问题描述】:

如果我正在执行此操作的函数是派生实例类的基类,我如何找出在 Python 中创建对象实例的类的名称?

当时在想the inspect module 可能会帮助我,但它似乎并没有给我想要的东西。由于无法解析 __class__ 成员,我不确定如何获取此信息。

【问题讨论】:

  • 您究竟从 class 变量中“解析”了什么?
  • 实例所属类的顶层名称(不含模块名等...)

标签: python introspection instanceof python-datamodel


【解决方案1】:

你试过班上的__name__ attribute吗?即type(x).__name__ 会给你班级的名字,我认为这是你想要的。

>>> import itertools
>>> x = itertools.count(0)
>>> type(x).__name__
'count'

如果您仍在使用 Python 2,请注意上述方法仅适用于 new-style classes(在 Python 3+ 中,所有类都是“新式”类)。您的代码可能会使用一些旧式类。以下适用于两者:

x.__class__.__name__

【讨论】:

  • 非常简单。想知道为什么dir(x.__class__) 没有列出它吗?
  • 为什么使用__class__ 而不是type 方法?像这样:type(x).__name__。不鼓励直接调用双下划线成员吗?不过,我看不到使用 __name__ 的方法。
  • 您必须直接使用__class__ 才能与旧式类兼容,因为它们的类型只是instance
  • 这在日志记录、orm 和框架代码中经常使用,以至于确实应该有一个内置的 typename(x) ... 要求用户查看“胆量”以获得 名字 不是很pythonic,IMO。
  • @ErikAronesty, def typename(x): return type(x).__name__
【解决方案2】:

你想要类名作为字符串吗?

instance.__class__.__name__

【讨论】:

  • 或者instance.__class__获取类对象:D
  • 使用双下划线属性安全吗?
  • @EduardLuca 为什么不安全?内置属性使用下划线,这样它们就不会与您编写的代码产生任何冲突
  • 嗯,我知道单下划线意味着/建议方法/属性应该是私有的(尽管您不能在 Python AFAIK 中真正实现私有方法),我想知道情况是否不是这样(一些)双下划线。
  • @EduardLuca 仅开头的双下划线类似于开头的单下划线,但更加“私密”(查找“python name mangling”)。开头和结尾的双下划线是不同的——它们是为python保留的,不是私有的(例如,像__init__和__add__这样的魔术方法)。
【解决方案3】:

type()?

>>> class A:
...     def whoami(self):
...         print(type(self).__name__)
...
>>>
>>> class B(A):
...     pass
...
>>>
>>>
>>> o = B()
>>> o.whoami()
'B'
>>>

【讨论】:

  • 我喜欢这个。这样,可以在基类中获取子类的名称。
  • self.__class__.__name__ 而不是 type(self).__name__ 以获得相同的行为。除非type() 函数有什么我不知道的吗?
  • 如果您在列表项上使用type(item),则结果将为<type 'instance'>,而item.__class__.__name__ 包含类名。
  • 我认为@Grochni 提到的问题仅与 Python 2.x 中的某些类有关,请参见此处:stackoverflow.com/questions/6666856/…
【解决方案4】:
class A:
  pass

a = A()
str(a.__class__)

上面的示例代码(在交互式解释器中输入时)将生成'__main__.A',而不是在调用__name__ 属性时生成的'A'。只需将A.__class__ 的结果传递给str 构造函数,即可为您处理解析。但是,如果您想要更明确的内容,也可以使用以下代码。

"{0}.{1}".format(a.__class__.__module__,a.__class__.__name__)

如果您在不同的模块中定义了同名的类,则此行为可能更可取。

上面提供的示例代码是在 Python 2.7.5 中测试的。

【讨论】:

    【解决方案5】:

    在 Python 2 中,

    type(instance).__name__ != instance.__class__.__name__
    # if class A is defined like
    class A():
       ...
    
    type(instance) == instance.__class__
    # if class A is defined like
    class A(object):
      ...
    

    例子:

    >>> class aclass(object):
    ...   pass
    ...
    >>> a = aclass()
    >>> type(a)
    <class '__main__.aclass'>
    >>> a.__class__
    <class '__main__.aclass'>
    >>>
    >>> type(a).__name__
    'aclass'
    >>>
    >>> a.__class__.__name__
    'aclass'
    >>>
    
    
    >>> class bclass():
    ...   pass
    ...
    >>> b = bclass()
    >>>
    >>> type(b)
    <type 'instance'>
    >>> b.__class__
    <class __main__.bclass at 0xb765047c>
    >>> type(b).__name__
    'instance'
    >>>
    >>> b.__class__.__name__
    'bclass'
    >>>
    

    【讨论】:

    • 这只适用于旧的 Python 2.x。在 3.x 中,bclass() 将解析为 bclass(object)。即便如此,Python 2.2 中也出现了新的类。
    【解决方案6】:

    您也可以使用 classmethod 装饰器:

    class A:
        @classmethod
        def get_classname(cls):
            return cls.__name__
    
        def use_classname(self):
            return self.get_classname()
    

    用法

    >>> A.get_classname()
    'A'
    >>> a = A()
    >>> a.get_classname()
    'A'
    >>> a.use_classname()
    'A'
    

    【讨论】:

      【解决方案7】:

      好问题。

      这是一个基于 GHZ 的简单示例,可能会对某人有所帮助:

      >>> class person(object):
              def init(self,name):
                  self.name=name
              def info(self)
                  print "My name is {0}, I am a {1}".format(self.name,self.__class__.__name__)
      >>> bob = person(name='Robert')
      >>> bob.info()
      My name is Robert, I am a person
      

      【讨论】:

        【解决方案8】:

        除了获取特殊的__name__ 属性外,您可能会发现自己需要给定类/函数的qualified name。这是通过获取__qualname__ 类型来完成的。

        在大多数情况下,它们是完全相同的,但是在处理嵌套类/方法时,它们的输出会有所不同。例如:

        class Spam:
            def meth(self):
                pass
            class Bar:
                pass
        
        >>> s = Spam()
        >>> type(s).__name__ 
        'Spam'
        >>> type(s).__qualname__
        'Spam'
        >>> type(s).Bar.__name__       # type not needed here
        'Bar'
        >>> type(s).Bar.__qualname__   # type not needed here 
        'Spam.Bar'
        >>> type(s).meth.__name__
        'meth'
        >>> type(s).meth.__qualname__
        'Spam.meth'
        

        由于内省是您所追求的,因此您始终可能需要考虑这一点。

        【讨论】:

        【解决方案9】:

        您可以简单地使用__qualname__,它代表函数或类的限定名称

        例子:

        >>> class C:
        ...     class D:
        ...         def meth(self):
        ...             pass
        ...
        >>> C.__qualname__
        'C'
        >>> C.D.__qualname__
        'C.D'
        >>> C.D.meth.__qualname__
        'C.D.meth'
        

        文档链接qualname

        【讨论】:

        • 这给出了一个类的名字而不是一个实例的类名
        【解决方案10】:

        获取实例类名:

        type(instance).__name__
        

        instance.__class__.__name__
        

        两者都一样

        【讨论】:

        猜你喜欢
        • 2015-06-01
        • 2011-04-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-14
        • 1970-01-01
        相关资源
        最近更新 更多