Отримання назви класу для екземпляра?


1436

Як я дізнаюся ім'я класу, який створив екземпляр об'єкта в Python, якщо функція, з якої я це роблю, є базовим класом, з якого був похідний клас екземпляра?

Думав, може, модуль перевірки, можливо, допоміг мені тут, але, здається, не дає мені того, чого я хочу. І якщо не розбирати __class__члена, я не знаю, як отримати цю інформацію.


Що саме ви "розбираєте" зі змінної класу ?
sykora

1
найвищого рівня класу, до якого належить екземпляр (без назви модуля тощо)
Dan

Я думаю, що навпаки було б набагато важче (отримати клас, у якому визначено метод / функцію).
Олексій

Відповіді:


1908

Ви спробували __name__атрибут класу? тобто type(x).__name__дасть вам назву класу, який я думаю, що ви хочете.

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

Якщо ви все ще використовуєте Python 2, зауважте, що вищевказаний метод працює лише з класами нового стилю (у Python 3+ усі класи є класами «нового стилю»). Ваш код може використовувати деякі класи старого стилю. Наступні роботи для обох:

x.__class__.__name__

41
Дивно просто. Цікаво, чому dir(x.__class__)його не перелічити?
cfi

43
Навіщо використовувати __class__над typeметодом? Як так: type(x).__name__. Чи не закликає членів подвійного підкреслення безпосередньо не перешкоджати? __name__Однак я не бачу способу використання .
jpmc26

25
Ви повинні використовувати __class__ безпосередньо, щоб бути сумісними з класами старого стилю, оскільки їх тип справедливий instance.
Quantum7

14
Це використовується досить часто при реєстрації, orm та рамковому коді, щоб дійсно повинно бути вбудоване ім'я типу (x) ... вимагає, щоб користувач дивився на "кишки", щоб отримати ім'я не дуже жахливе, IMO.
Ерік Аронесті

5
@ErikAronesty, def typename(x): return type(x).__name__
sleblanc

390

Ви хочете, щоб назва класу була рядком?

instance.__class__.__name__

6
Або, наприклад, .__ class__, щоб отримати об’єкт класу: D
Pencilcheck

8
Чи безпечно використовувати подвійні властивості підкреслення?
Едуард Лука

5
@EduardLuca чому б це не було безпечно? Вбудовані властивості використовують підкреслення, щоб вони не викликали конфлікту з
написаним

3
Я знаю, що окремі підкреслення означають / підказують, що метод / властивість має бути приватним (хоча ви не можете реально реалізувати приватні методи в Python AFAIK), і мені було цікаво, чи не так це і з (деякими) подвійними підкресленнями.
Едуард Лука

28
@EduardLuca Подвійні підкреслення лише на початку схожі на окремий підкреслення на початку, але ще більше "приватне" (шукайте "керування ім'ям пітона"). Подвійні підкреслення на початку та в кінці різні - вони зарезервовані для python і не є приватними (наприклад, магічні методи, такі як __init__ та __add__).
Leagsaidh Gordon

100

type ()?

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

це те саме, що і для класу , але мені потрібно розібрати цей результат вручну, що трохи дратує ...
Dan

8
Мені це подобається. Таким чином, в базовому класі можна отримати назву підкласу.
Joctee

6
або self.__class__.__name__замість того, type(self).__name__щоб отримати таку саму поведінку. Якщо є якась type()функція, про яку я не знаю?
andreb

2
Якщо ви використовуєте type(item)на елемент списку буде результат , <type 'instance'>поки item.__class__.__name__тримає ім'я класу.
Грочні

1
Я думаю, що питання, про яке згадує @Grochni, є актуальним лише для певних класів у Python 2.x, дивіться тут: stackoverflow.com/questions/6666856/…
Nate CK

43
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.


Випробувано в 2.6.6. Ще добре працює.
Гамлет

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

5
Це справедливо лише для старого Python 2.x. У 3.x, bclass () буде вирішувати bclass (об'єкт). І вже тоді в Python 2.2 з’явилися нові класи.
alcalde

16

Хороше питання.

Ось простий приклад на основі 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

Ви також можете використовувати 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'

10

Окрім захоплення спеціального __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'

Оскільки інтроспекція - це те, за чим ви хочете, це завжди, що ви можете подумати.


2
Слід зазначити, що __qualname__для Python 3.3+
FireAphis

10
І я б уникав називати що-небудь у своєму програмному забезпеченні "мет".
Бобборт

Пов'язані пояснення __qualname__проти __name__: stackoverflow.com/questions/58108488/what-is-qualname-in-python
ti7

0

Щоб отримати ім'я класу екземпляра:

type(instance).__name__

або

instance.__class__.__name__

обидва однакові

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.