У декоратора Python нет ожидаемого модуля / имени - PullRequest
0 голосов
/ 22 февраля 2020

Как я могу применить «шаблон подкласса», но чтобы класс «показывался» (как в модуле / имени) приходил с именем, которое я ему дал, из модуля, который я его сделал , и не из модуля Я сделал создатель .

Без сомнения, и пример оправдан здесь. Скажем, у меня есть модули:

# module_with_wrapper.py
from functools import wraps

def my_wrap(cls, name=None):
    assert isinstance(cls, type)
    class WrappedClass(cls):
        @wraps(cls.__init__)
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.something_else = 42
    WrappedClass.__name__ = name or f"{cls.__name__}Wrapped"
    return WrappedClass

, используемые в следующем модуле:

# a_module.py
from functools import wraps

class A:
    def __init__(self, a):
        self.a = a

class B(A):
    @wraps(A.__init__)
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.something_else = 42

from module_with_wrapper import my_wrap

BB = my_wrap(A, 'BB')  # define class BB, expected to be equivalent to B

Цель состоит в том, чтобы иметь возможность повторно использовать шаблон подклассов, указанный с помощью B, в любом месте, где я хочу , с любым классом, который я хочу.

И это работает, но модуль / имя не то, что я ожидаю. Я ожидаю, что мой BB будет отображаться как a_module.BB, а не как module_with_wrapper.my_wrap.<locals>.WrappedClass!

>>> from a_module import B, BB
>>>
>>> B
<class 'a_module.B'>
>>> b = B(a=0)
>>> b
<a_module.B object at 0x10e40eb50>
>>>
>>> BB  # what the?! I thought I told it it's name was BB!!
<class 'module_with_wrapper.my_wrap.<locals>.WrappedClass'>
>>> bb = BB(a=0)
>>> bb
<module_with_wrapper.my_wrap.<locals>.WrappedClass object at 0x10e40ebd0>
>>> BB.__name__  # okay, at least it got THAT right!
'BB'

1 Ответ

1 голос
/ 22 февраля 2020

Хотя repr использовал атрибут __name__ в python 2, в python 3 (> = 3.3) он использует новый атрибут __qualname__ для предоставления большего контекста. Если вы переопределите __qualname__ в своем декораторе, вы получите желаемый результат.

См. этот вопрос для получения дополнительной информации об атрибуте __qualname__.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...