#python #python-3.x
#python #python-3.x
Вопрос:
Я работаю над декоратором, который запускает функцию для первого аргумента оформленного метода, который не self
является. Для достижения этой цели я в настоящее время использую два декоратора с практически одинаковым кодом. Единственное отличие состоит в том, что у вас есть функция, которая содержит self перед первым аргументом.
import functools
def wrap(function):
@functools.wraps(function)
def wrapper(first_argument, *args, **kwargs):
someFuntion(first_argument)
return function(first_argument, *args, **kwargs)
return wrapper
def wrapClass(function):
@functools.wraps(function)
def wrapper(self, first_argument, *args, **kwargs):
someFuntion(first_argument)
return function(self, first_argument, *args, **kwargs)
return wrapper
Я хотел бы объединить два декоратора в один в таком формате:
import functools
def wrap(function):
if isPartOfClass(function):
@functools.wraps(function)
def wrapper(self, first_argument, *args, **kwargs):
someFuntion(first_argument)
return function(self, first_argument, *args, **kwargs)
else:
@functools.wraps(function)
def wrapper(first_argument, *args, **kwargs):
someFuntion(first_argument)
return function(first_argument, *args, **kwargs)
return wrapper
Раньше в Python 2 я мог просто определить, была ли функция несвязанным методом. Однако я знаю, что эта концепция была удалена в Python 3.
Я уже придумал несколько методов обнаружения, которые не будут работать.
- Я мог бы сначала проверить, вызывается ли первый аргумент
self
, но это не обязательное имя. - Я мог бы попытаться определить, имеет ли функция 1 (обычный) или 2 (класс) аргументы, но обычная функция может содержать более 1 аргумента. Независимо от количества аргументов, меня интересует только первый аргумент, который не является self .
- Я мог бы попытаться определить первый аргумент на основе типа, но нет никакой гарантии, какого именно типа он будет.
Есть ли у меня какой-либо практический способ сделать это обнаружение, или я застряну с двумя декораторами?
Комментарии:
1. В то время, когда декоратор применяется к методу, написанному в
class
блоке, метод не является «частью» класса. Объект, представляющий класс, не создается до тех пор, пока не будут созданы все объекты, представляющие методы (которые на данный момент все еще являются обычными функциями).
Ответ №1:
Будет ли проверка __qualname__
для вашего usecase?
In [19]: class Foo:
...: def __init__(self, x):
...: self.x = x
...: def __str__(self): return "foo"
...: def __repr__(self): return f"Foo({self.x})"
...: def bar(self): return 1
...:
In [20]: b = Foo.bar
In [21]: b
Out[21]: <function __main__.Foo.bar(self)>
In [22]: b.__qualname__
Out[22]: 'Foo.bar'
Наличие .
в __qualname__
должно быть явным признаком метода в классе. Другие функции этого не имеют:
In [24]: print.__qualname__
Out[24]: 'print'
Для не встроенной функции
In [25]: def foo(x): return ''
In [26]: foo.__qualname__
Out[26]: 'foo'
Для импортированной функции:
In [23]: inspect.getargs.__qualname__
Out[23]: 'getargs'
Комментарии:
1. Это будет сделано, если что-то еще, что обертывает его должным образом, сохраняет полное имя, а также сохраняет свойство в первую очередь. Я обнаружил, что одна из оболочек, которые я на самом деле использую (к счастью, та, которая всегда выполняется последней, поэтому это не влияет на это), фактически полностью удалила свойство. Спасибо.