Я только начал использовать декораторы в Python, и я не уверен, что понимаю, как правильно его использовать.

Допустим, у меня есть этот код:

def viable_decorator(fonction_viable):
    def viable(sequences, pos):
        codons = [seq[pos:pos+3] for seq in sequences]
        return not any("-" in codon for codon in codons)
    return viable

@viable_decorator
def viable(sequences, pos):
    codons = [seq[pos:pos+3] for seq in sequences]
    return not all("-" in codon for codon in codons)

sequncess = ["---aaacacaacaacaaat",
             "------aaacacacac---",
             "aaggcggaggcgg---ggg",]

print viable(sequences, 0)

Моя цель - иметь возможность поочередно использовать две версии функции viable() в зависимости от ситуации. Это как декораторы должны работать? И если да, как я могу определить выбор функции viable()? Потому что сейчас в этом коде декоратор всегда вызывается.

Заранее спасибо.

4
Micawber 24 Фев 2018 в 22:55

3 ответа

Лучший ответ

Это как декораторы должны работать?

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

В вашем конкретном случае:

def viable_decorator(fonction_viable):
    def viable(sequences, pos):
        codons = [seq[pos:pos+3] for seq in sequences]
        return not any("-" in codon for codon in codons)
    return viable

Декоратор даже не использует декорированную функцию fonction_viable. Конечно, это синтаксически допустимо, но это не то, что декоратор, как следует из названия, должен делать.

4
llllllllll 24 Фев 2018 в 20:02

В Python3 вы можете использовать functools.wraps для создания упакованной и развернутой версии viable:

import functools
def viable_decorator(fonction_viable):
  @functools.wraps(fonction_viable)
  def viable(sequences, pos):
    codons = [seq[pos:pos+3] for seq in sequences]
    return not any("-" in codon for codon in codons)
  return viable

@viable_decorator
def viable(sequences, pos):
   codons = [seq[pos:pos+3] for seq in sequences]
   return not all("-" in codon for codon in codons)

unwrapped_viable = viable.__wrapped__

В этом примере вызов viable в свою очередь вызовет viable_decorator. Однако вызов unwrapped_viable вызовет viable без запуска viable_decorator.

1
Ajax1234 24 Фев 2018 в 19:57

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

Попытайтесь представить декораторы как сущности более высокого порядка, которые добавят что-то, что они украшают

1
randyjp 24 Фев 2018 в 20:11