Передать имя класса в функцию, присвоить атрибуту класса вне метода - PullRequest
2 голосов
/ 16 апреля 2019

Python 3.7:

У меня есть определение класса, где атрибуту класса присваивается значение на основе имени класса, и это значение используется в декораторе в классе.

Я ищу местоимение для "класса в настоящее время определяется".

Вот пример:

class MyClass:

    # NameError: name '__class__' is not defined
    class_logger = find_logger(__class__.__name__)

    # __init__ is not important
    def __init__(self):
        # This works!
        self.logger = find_logger(__class__.__name__)

    @mydecorator(class_logger)
    # mymethod is not important
    def mymethod(self):
        return 1

Какое местоимение подходит для "определяемого в настоящее время класса"?

(Это похоже на Как получитьтекущее имя класса Python в __init__ независимо от класса «self»? , но там вопрос был «в определении init », а в то время был для 2.7. Python 3.x решил эту проблему.)

Ответы [ 2 ]

4 голосов
/ 16 апреля 2019

Не гарантируется, что объект класса существует и доступен пользователю, когда определение класса еще не завершило оценку. Даже если он был доступен, он не мог быть инициализирован в той степени, в которой вы могли бы сделать с ним что-нибудь полезное.

Тем не менее, вы можете получить название класса. __qualname__ - это атрибут, который содержит квалифицированное имя экземпляра класса / функции / метода / дескриптора / генератора. Вы должны иметь доступ к нему из определения класса.

class Fred:
    print("Fred's qualname:", __qualname__)
    class Barney:
        print("Barney's qualname:", __qualname__)

Результат:

Fred's qualname: Fred
Barney's qualname: Fred.Barney

Если ваш класс не определен на уровне файлов, вам может потребоваться выполнить некоторые манипуляции со строками, чтобы отделить его имя от остальной части пути. Например, измените приведенный выше пример на print("Barney's qualname:", __qualname__.rpartition(".")[-1]), чтобы получить просто «Барни», а не «Фред. Барни».


Несмотря на все мои усилия, я не смог найти документацию, которая явно подтверждает, что __qualname__ имеет разумное значение при доступе как обычное имя, а не как атрибут. Я не совсем уверен, что это четко определенное поведение, поэтому я не думаю, что могу безоговорочно одобрить его для кода производственного качества.

2 голосов
/ 16 апреля 2019

Для работы с именем класса во время его определения вы также можете использовать метакласс с __prepare__ методом:

def find_logger(name):
    return name + '_logger'


class PrepareClassLogger(type):
    def __prepare__(name, bases, **kwargs):
        return {'class_logger': find_logger(name)}


class MyClass(metaclass=PrepareClassLogger):
    pass

print(MyClass.class_logger)  # MyClass_logger
...