Python, как получить __qualname__ метода, обернутого с помощью property.setter

У меня есть атрибут экземпляра, который я сделал свойством с помощью декоратора Python property.

Затем я создал сеттер для свойства с помощью декоратора @property_name.setter.

Как я могу получить __qualname__ исходного определения метода, украшенного @property.setter?


Где я искал


Пример кода

Это было написано в Python 3.6.

#!/usr/bin/env python3


def print_qualname():
    """Wraps a method, printing its qualified name."""

    def print_qualname_decorator(func):
        # print(f"func = {func} and dir(): {dir(func)}")
        if hasattr(func, "__qualname__"):
            print(f"Qualified name = {func.__qualname__}.")
        else:
            print("Doesn't have qualified name.")

    return print_qualname_decorator


class SomeClass:

    def __init__(self):
        self._some_attr = 0
        self._another_attr = 0

    @property
    def some_attr(self) -> int:
        return self._some_attr

    @print_qualname()
    @some_attr.setter
    def some_attr(self, val: int) -> None:
        self._some_attr = val

    @print_qualname()
    def get_another_attr(self) -> int:
        return self._another_attr

Выход:

Doesn't have qualified name.
Qualified name = SomeClass.get_another_attr.

Как я могу получить __qualname__ для some_attr из декоратора print_qualname? Другими словами, как мне вывести SomeClass.some_attr?


person Intrastellar Explorer    schedule 12.12.2019    source источник


Ответы (1)


Вы можете перевернуть порядок декораторов для сеттера. Примечание. Я настроил print_qualname_decorator так, чтобы он вызывал базовую функцию и возвращал ее (иначе установщик не будет выполняться).

from functools import wraps

def print_qualname(func):
    """Wraps a method, printing its qualified name."""
    @wraps(func)
    def print_qualname_decorator(*args):
        if hasattr(func, "__qualname__"):
            print(f"Qualified name = {func.__qualname__}.")
        else:
            print("Doesn't have qualified name.")
        return func(*args)
    return print_qualname_decorator


class SomeClass:

    def __init__(self):
        self._some_attr = 0
        self._another_attr = 0

    @property
    def some_attr(self) -> int:
        return self._some_attr

    @some_attr.setter
    @print_qualname
    def some_attr(self, val: int) -> None:
        self._some_attr = val

    @print_qualname
    def get_another_attr(self) -> int:
        return self._another_attr

Использовать

In [46]: foo = SomeClass()                                               

In [47]: foo.get_another_attr()                                          
Qualified name = SomeClass.get_another_attr.
Out[47]: 0

In [48]: foo.some_attr = 5                                               
Qualified name = SomeClass.some_attr.

In [49]: foo._some_attr                                                  
Out[49]: 5
person Kent Shikama    schedule 17.12.2019
comment
Спасибо, @KentShikama! я об этом не подумала - person Intrastellar Explorer; 17.12.2019