Python-декоратор для подсегментов функций - PullRequest
0 голосов
/ 01 декабря 2018

Есть ли в 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: Теперь мне кажется, что у меня нет другого выбора, кроме как ожидать, что пользователи фреймворка как-то объявят именованные функции ...

Ответы [ 4 ]

0 голосов
/ 01 декабря 2018

Тела функций скомпилированы в единый объект «код», который выполняется как единое целое - изменяя способ выполнения этого объекта кода, вставляя в него что-то, и такие вещи могут быть такими же сложными, как и сам код языка (т. е. код, который на самом деле «выполняет» байт-код 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 голосов
/ 01 декабря 2018

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

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

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

  doubler(lambda: print("world"))

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

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

0 голосов
/ 01 декабря 2018

Просто объявите две функции с любым именем с помощью декоратора @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 голосов
/ 01 декабря 2018

Вам придется извлечь эту частичную функциональность 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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...