题 在Python中获取实例的类名


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

也许在想 检查模块 可能在这里帮助了我,但它似乎没有给我我想要的东西。而且解析不了 __class__ 会员,我不知道如何获取这些信息。


1007
2018-02-04 11:37


起源


究竟是什么'解析'了 类 变量? - sykora
实例所属类的顶级名称(没有模块名称等) - Dan
我认为相反的方法会更难(获得定义方法/函数的类)。 - Alexey


答案:


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

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

这种方法适用 新式课程 只要。您的代码可能会使用一些旧式类。以下适用于:

x.__class__.__name__

1346
2018-02-04 12:02



非常简单。想知道为什么 dir(x.__class__) 不列出吗? - cfi
为何使用 __class__ 过了 type 方法?像这样: type(x).__name__。是不是直接打电话给双下划线成员?我看不到使用方法 __name__但是。 - jpmc26
你必须使用 __class__ 直接与旧式类兼容,因为它们的类型只是 instance。 - Quantum7
因为我使用它是在一个 __getattr__ 方法,如果我寻求任何属性 self,我得到一个递归错误。运用 type 在那种情况下至关重要。 - Bobort
这在日志记录,orm和框架代码中经常被使用,它们确实应该是内置类型名称(x)...要求用户查看“guts”以获取 名称 IMO并不是非常恐怖的。 - Erik Aronesty


你想把类的名字作为字符串吗?

instance.__class__.__name__

284
2018-02-04 12:02



或者实例.__ class__来获取类对象:D - Pencilcheck
使用双下划线属性是否安全? - Eduard Luca
@EduardLuca为什么不安全?内置属性使用下划线,这样它们就不会与您编写的代码产生任何冲突 - J. C. Rocamonde
我知道单个下划线意味着/建议方法/属性应该是私有的(虽然你不能在Python AFAIK中真正实现私有方法),我想知道是否也不是(某些)双下划线的情况。 - Eduard Luca
@EduardLuca一开始的双重下划线在开始时类似于单个下划线,但更加“私有”(查找“python name mangling”)。开始时双下划线 并结束 是不同的 - 这些是为python保留的,不是私有的(例如__init__和__add__等魔术方法)。 - Leagsaidh Gordon


type()?

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

70
2018-02-04 11:42



这和 类 会员,但我必须手工解析这个结果,这有点烦人...... - Dan
我喜欢这一个。这样,在基类中可以获取子类的名称。 - joctee
要么 self.__class__.__name__ 代替 type(self).__name__ 得到相同的行为。除非有什么东西 type() 我不知道的功能吗? - andreb
如果你正在使用 type(item) 在列表项上,结果将是 <type 'instance'> 而 item.__class__.__name__ 持有班级名称。 - Grochni
我认为@Grochni提到的问题仅与Python 2.x中的某些类有关,请参见此处: stackoverflow.com/questions/6666856/... - Nate C-K


class A:
  pass

a = A()
str(a.__class__)

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

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

如果您在单独的模块中定义了具有相同名称的类,则此行为更可取。

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


26
2018-06-09 23:04



测试3.5。仍然运作良好。 - cmp


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

24
2018-04-30 05:50



这仅适用于旧的Python 2.x.在3.x中,bclass()将解析为bclass(object)。即便如此,Python 2.2中出现了新的类。 - alcalde


好问题。

这是一个基于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

13
2018-02-21 19:07





除了抓住特别的 __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'

由于内省是你所追求的,所以你可能总是想要考虑。


4
2017-07-12 15:01



应该注意的是 __qualname__ 适用于Python 3.3+ - FireAphis
我会避免在我的软件“meth”中命名任何内容。 - Bobort


或者你可以使用 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'

4
2017-09-13 19:11