Отримати ім’я поточного класу?


102

Як отримати назву класу, в якому я зараз перебуваю?

Приклад:

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

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

Через характер програми, з якою я взаємодію (vistrails), я не можу використовувати її __init__()для ініціалізації input.

Відповіді:


158

obj.__class__.__name__ отримає вам будь-яке ім’я об’єктів, тож ви можете це зробити:

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

Використання:

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

1
Чому це не прийнята відповідь? РЕДАКТУВАННЯ: Гаразд ОП не є внутрішнім, це на рівні класу.
KomodoDave

6
@KomodoDave, оскільки це помилково, навіть в області застосування методу. Коли ви телефонуєте getNameз дочірнього класу, він видасть ім'я дочірнього класу. Потім це стає складним, якщо ви дійсно хочете класу, з яким працюєте.
Кенет Джервет

@KenetJervet Ви маєте на увазі, коли ви телефонуєте getNameз батьківського класу, він видасть ім'я дочірнього класу? Гаразд, ти вказуєш на це.
KomodoDave

5
У OO-термінах рішення (повернення фактичного імені дочірнього класу часу виконання, навіть якщо getName()метод визначений у суперкласі) є правильним.
sxc731

22

У тілі класу ім'я класу ще не визначено, тому воно недоступне. Ви не можете просто ввести назву класу? Можливо, вам потрібно сказати більше про проблему, щоб ми могли знайти рішення для вас.

Я б створив метаклас, щоб зробити цю роботу за вас. Він викликається під час створення класу (концептуально в самому кінці класу: block) і може маніпулювати класом, що створюється. Я цього не перевіряв:

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'

Щоб пояснити, що я намагаюся зробити: мені потрібно створити та ініціалізувати змінну класу, 'input', поза методом . У мене є купа невеликих класів, кожен з яких повинен викликати 'get_input', використовуючи своє ім'я класу як параметр. Я намагаюся узагальнити це, тому мені не потрібно ходити до кожного класу (їх буде близько 100) і вводити назву класу.
Джонатан Гінзбург,

Добре, я оновив свою відповідь метакласом, який повинен допомогти.
Ned Batchelder,

1
Що MyTypeв superрядку в InputAssigningMetaclassсм?
A.Wan

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

EDIT: Так, ви можете; але вам потрібно обдурити: назва класу, що виконується на даний момент, присутня в стеку викликів, і 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'

Однак я б цього не робив; Моя оригінальна відповідь - це все-таки власні переваги як рішення. Оригінальна відповідь:

мабуть, найпростішим рішенням є використання декоратора, який схожий на відповідь Неда, що стосується метакласів, але менш потужний (декоратори здатні до чорної магії, але метакласи здатні до старовинної, окультної чорної магії)

>>> 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()

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