Python-декоратор для подсегментов функций

1

В Python есть ли хороший способ применить декоратор (или нечто подобное) не к целой функции, а к подсегменту тела функции?

То, что я хочу, может выглядеть примерно так:

def deco_double(f):
    def wrapper():
            f()
            f()
    return wrapper

def foo():
    @deco_double:
        print("hello")
        print("stack")
    @deco_double:
        print("overflow")

foo()

Таким образом, результат выполнения будет выглядеть следующим образом:

hello
stack
hello
stack
overflow
overflow

Это нормально, если решение не является точно декортером, мне нужен метод обертки функциональных подсегментов, но в абстрактном виде. Заранее спасибо :)

edit: Простое разделение на несколько функций для меня не является вариантом. Я разрабатываю рамки для программистов, и я хочу, чтобы они записывали функции в компактном виде (для написания foo() в примере. Кроме того, то, что я на самом деле делаю, намного сложнее, чем просто повторения)

edit2: Похоже, у меня нет выбора, кроме как ожидать, что пользователи инфраструктуры каким-то образом объявят именованные функции...

  • 0
    Просто используйте больше функций.
  • 0
    Вы говорите, что разделение на несколько функций не вариант, а затем в ответе вы принимаете, что вы идете вперед и делаете именно это.
Теги:
decorator
python-decorators

4 ответа

1
Лучший ответ

Органы функций скомпилированы в один "кодовый" объект, который запускается в целом, - изменяя способ запуска этого объекта кода, вставляя в него вещи, и такие вещи могут быть такими же сложными, как сам код языка (то есть код что фактически "исполняет" байт-код Python).

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

Если вы хотите получить эквивалент общего декоратора по частям внутри тела функции, проще всего это разделить эту функцию на внутренние функции, а затем вы можете применить свои преобразования или выполнить каждую часть более одного раза, просто позвонив эти функции (и даже украсить их напрямую).

Однако, в случае, вы приносите в вашем вопросе, вы можете, и, вероятно, следует просто использовать обычный старый for цикла:

def foo():
    for _ in (0, 1):
        print("hello")
        print("stack")
    for _ in (0, 1):
        print("overflow")

Для произвольного "поведения декоратора", как я писал выше, просто используйте вложенные функции:

def foo():
    @deco_double
    def part1()
        print("hello")
        print("stack")
    part1()
    @deco_double:
    def part2():
        print("overflow")
    part2()
  • 0
    Я ценю ваше объяснение о выполнении кода Python :) На самом деле я делаю гораздо больше, чем просто циклы. Быть сжатым - это ключ к тому, что я делаю (фреймворк), поэтому я думаю, что лямбда-выражения лучше соответствуют моим требованиям, чем вложенные функции.
  • 0
    Хорошо, теперь я понимаю, что нет многострочных лямбда-выражений. Я думаю, что это лучший вариант.
Показать ещё 1 комментарий
0

Просто объявите две функции с любым именем с декоратором @deco_double и вызовите их в любой другой функции, в вашем случае foo() а затем просто вызовите foo().

def deco_double(f):
    def wrapper():
            f()
            f()
    return wrapper
@deco_double
def func1():
     print("hello")
     print("stack")
@deco_double
def func2():
     print("overflow")
def foo():
    func1()
    func2()
foo()

Вывод этого кода.

hello
stack
hello
stack
overflow
overflow
0

Вам, вероятно, понадобится передать функции, используя lambda если вы хотите достичь этого:

def doubler(f):
  f()
  f()

def foo():
  doubler(lambda: print("hello"))

  doubler(lambda: print("world"))

foo()
"hello"
"hello"
"world"
"world"

Оберните код, который вы хотите дважды запустить в lambda, и передайте функцию doubler

  • 0
    Я думаю, что использование лямбда-выражения было то, что я должен был рассмотреть, спасибо!
  • 0
    Они часто полезны для обобщения кода и уменьшения дублирования.
Показать ещё 3 комментария
0

Вам нужно будет извлечь эту частичную функциональность foo() для разделения функций, а затем применить декоратор как функцию и называть его истечением.

def deco_double(f):
    def wrapper():
            f()
            f()
    return wrapper

def my_f1():
     print("hello")
     print("stack")

def my_f2():
     print("overflow")

def foo():
    deco_double(my_f1)()
    deco_double(my_f2)()

foo()

Ещё вопросы

Сообщество Overcoder
Наверх
Меню