Как обернуть стороннего декоратора моим собственным в python

#python #python-3.x #amazon-web-services #decorator #python-decorators

#питон #python-3.x #amazon-веб-сервисы #оформитель #питон-декораторы

Вопрос:

Я вижу много примеров обертывания декораторов своими собственными, но все они касаются пользовательских декораторов. У меня есть сторонний декоратор, который можно использовать, например:

 @someSDK myFunction()  

что я хочу сделать, так это обернуть это в свой собственный декоратор, который вызывает @someSDK только в том случае, если env имеет значение true

ПРАВКА: в частности, декоратор третьей стороны @xray_recorder.capture() . Мне нужен мой собственный декоратор, который будет реализовывать это только в том случае, если у меня есть переменная, установленная в качестве определенного флага.

Это то, что у меня пока есть приблизительное представление:

 if CUSTOM_XRAY_WRAPPER is True:  @xray_recorder.capture()  def wrapper(*args, **kwargs):  val = func(*args, **kwargs)  return val  return wrapper else:  def wrapper(*args, **kwargs):  val = func(*args, **kwargs)  return val  return wrapper  

Ответ №1:

В качестве небольшого примера, поскольку вы не привели минимального воспроизводимого примера:

 CUSTOM_XRAY_WRAPPER = True  def xray_capture(func):  def wrapper(*args, **kwargs):  print('recodring')  return func(*args, **kwargs)  return wrapper  def yourdecorator(func):  if CUSTOM_XRAY_WRAPPER:  return xray_capture(func)  return func  @yourdecorator def yourfunction(text):  print(text)  

Здесь использование xray_capture декоратора для функции выводит «запись» перед выполнением этой функции. Вместо этого функцию yourdecorator можно использовать в качестве декоратора, который возвращает либо обычную функцию как есть, если значение CUSTOM_XRAY_WRAPPER равно False. Если это правда, он возвращает функцию, украшенную xray_capture .

Кстати, вам не нужно писать CUSTOM_XRAY_WRAPPER == True , так как это уже либо Правда, либо Ложь, что означает, что вы проверяете, является ли True == True или False == True .

В вашем примере это будет выглядеть так:

 def yourdecorator(func):  if CUSTOM_XRAY_WRAPPER:  xray_recorder.capture()(func)  return func  

Комментарии:

1. Неверно ли то, как я это сделал, добавив аннотацию перед оберткой?

2. Что ж, ваша версия определенно неверна. Насколько я вижу, вы никогда на самом деле не определяете настоящего декоратора. Вы определяете функцию-оболочку ony.

Ответ №2:

Что вам нужно помнить, так это то, что

 @decorator def foobar():  ...  

эквивалентно

 def foobar():  ... foobar = decorator(foobar)  

Итак, чего ты хочешь, так это

 def my_decorator(f):  if CUSTOM_XRAY_WRAPPER:  return xray_recorder.capture()(f)  else:  return f  

Ответ №3:

Вы можете переименовать декоратора и использовать сквозной:

 from functools import wraps   MY_ENV_VAR = True   # create a pass-through wrapper def sample_decorator(f):  @wraps(f)  def wrapper(*args, **kwargs):  return f(*args, **kwargs)  return wrapper   # now you can just use the same decorator everywhere if MY_ENV_VAR:  # use your recorder.capture   x_ray_capture = xray_recorder.capture() else:  # pass-through  x_ray_capture = sample_decorator   @x_ray_capture def foo():  # do something  

Комментарии:

1. разве это не должно быть xray_recorder.capture() в первом случае, если?

2. @qaispak это должно быть исправлено