Убедитесь, что функция, созданная динамически внутри класса, также может использоваться как отдельная функция и как метод класса - PullRequest
0 голосов
/ 05 октября 2019

Это расширение Динамически декорировать функцию внутри класса в Python3

@ MisterMyagi правильно ответил на мой вопрос, что вы можете динамически декорировать класс с помощью этой логики:

class MyTaskSequence(TaskSequence):
    pass


def add_sequence(cls, order, path):
    @seq_task(order)
    def sequence(self):
        self.client.get(path)
    sequence.__name__ = "sequence%d" % order
    setattr(cls, sequence.__name__, sequence)

add_sequence(MyTaskSequence, 1, "/devops/")
add_sequence(MyTaskSequence, 2, "/blog/")

Мой вопрос таков: как вы гарантируете, что сгенерированная функция может одновременно использоваться как автономная функция и как метод класса?

Например: определение статической функции:

class MyTaskSequence(TaskSequence):
    @seq_task(1)
    def sequence1(self):
        self.client.get("/devops/")

    @seq_task(2)
    def sequence2(self):
        self.client.get("/blog/")

pprint(vars(MyTaskSequence))


>>>> 

mappingproxy({'__doc__': None,
              '__module__': 'run-loadtest.index',
              'sequence1': <function start.<locals>.MyTaskSequence.sequence1 at 0x10d759c20>,
              'sequence2': <function start.<locals>.MyTaskSequence.sequence2 at 0x10d759f80>,
              'tasks': [<function start.<locals>.MyTaskSequence.sequence1 at 0x10d759c20>,
                        <function start.<locals>.MyTaskSequence.sequence2 at 0x10d759f80>]})

То, что я пробовал:

class MyTaskSequence(TaskSequence):
    pass


def add_sequence(cls, order, path):
    @seq_task(order)
    def sequence(self):
        self.client.get(path)
    sequence.__name__ = "sequence%d" % order
    setattr(cls, sequence.__name__, sequence)

add_sequence(MyTaskSequence, 1, "/devops/")
add_sequence(MyTaskSequence, 2, "/blog/")

pprint(vars(MyTaskSequence))


>>>> 

mappingproxy({'__doc__': None,
              '__module__': 'run-loadtest.index',
              'sequence1': <function start.<locals>.add_sequence.<locals>.sequence at 0x10590bc20>,
              'sequence2': <function start.<locals>.add_sequence.<locals>.sequence at 0x10590bf80>,
              'tasks': []})

Обратите внимание, что результирующий объект немного "отличается".

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

Youможно проверить это, сравнив полученное «определение» двух отпечатков:

 'sequence1': <function start.<locals>.MyTaskSequence.sequence1 at 0x10d759c20>,

VERSUS

'sequence1': <function start.<locals>.add_sequence.<locals>.sequence at 0x10590bc20>,

PS: обратите внимание на отсутствующее имя класса в его определении.

...