Как создать новый экземпляр класса в рекурсии - PullRequest
0 голосов
/ 02 июня 2019

Недавно я изучал алгоритм выравнивания последовательностей.После того, как я получил матрицу выравнивания, я смог найти оптимальный путь, но у меня возникли проблемы, когда я искал несколько оптимальных путей (возвратный путь)!

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

  1. Какие условия для выхода из рекурсии
  2. Когда мне нужно создать новый экземпляр, а когда я его не создаю?

Но проблема во втором условии.Я не знаю, сколько существует оптимальных результатов, и я не знаю, сколько будет создано новых экземпляров.

Поэтому я хочу иметь возможность динамически генерировать имя экземпляра с помощью переменной.

Я не знаю, как это сделать:

# those equivalent to new_instance_name = ResultSeq()
a="new_instance_name"
create_new_instance(a,ResultSeq)

Мой базовый класс результатов - ResultSeq:

class KeepRefs(object):
    """
    reference:/304229/pechat-vseh-ekzemplyarov-klassacomment167339_328851
    """
    __refs__ = defaultdict(list)

    def __init__(self):
        self.__refs__[self.__class__].append(weakref.ref(self))

    @classmethod
    def get_instances(cls):
        for inst_ref in cls.__refs__[cls]:
            inst = inst_ref()
            if inst is not None:
                yield inst


class ResultSeq(KeepRefs):
    """
    save two
    """
    def __init__(self, seq1="", seq2=""):
        super(ResultSeq, self).__init__()
        self.seq1 = seq1
        self.seq2 = seq2

Ниже приведен мой рекурсивный код:

def multi_backtracking(self, array, i, j, result_seq):
    """
    :param array: V, E, F
    :param i: row
    :param j: col
    :param result_seq: new instance of the class ResultSeq
    :return: Multiple alignment results
    """

    def create_new_obj(name, obj):
        """
        I don't know how to do this.
        """
        pass

    if i == 0 and j == 0:
        pass
    else:
        if array is self.array_V:
            if sum(pass_judgement) == 1:
                """
                An optimal path without creating a new instance.
                """
                self.multi_backtracking(self.array_V, i, j, result_seq)
            else:
                """
                Multiple paths, need to create a new instance
                """
                new_instance_name = "xxx"
                create_new_obj(new_instance_name, ResultSeq)
                ...
                if pass_judgement[0]:
                    result_seq.seq1 = self.origin_seq.seq1[i - 1] + result_seq.seq1
                    result_seq.seq2 = self.origin_seq.seq2[j - 1] + result_seq.seq2
                    self.multi_backtracking(self.array_V, i - 1, j - 1, new_instance_name)
                if pass_judgement[1]:
                    self.multi_backtracking(self.array_E, i, j, new_instance_name)
                if pass_judgement[2]:
                    self.multi_backtracking(self.array_F, i, j, new_instance_name)

Это только одно из моих решений.Если есть предложения получше, я буду рад их принять, спасибо!

1 Ответ

0 голосов
/ 02 июня 2019

Вам не нужны имена для хранения переменных - вы можете использовать простой список для хранения ваших экземпляров:

class A:
    def __init__(self,value):
        self.value = value
    def __repr__(self):
        return f" _{self.value}_ "

def rec(i):
    """Recursive function, returns a list of instances of class A with decreasing
    value i""" 
    if i < 0:
        return []

    return [A(i)] + rec(i-1) 

k = rec(5)
print(k)

Выход:

[ _5_ ,  _4_ ,  _3_ ,  _2_ ,  _1_ ,  _0_ ]

Вы можете получить доступ к своим экземплярам в своем списке, проиндексировав:

print(k[2])   # _3_

print(k[2].value + k[3].value)  # 5

Если вам действительно нужны имена, вы можете использовать словарь для их хранения - это примерно так же, как ваш существующий базовый класс KeepRefs делает (*):

data = { "Instance1" : A(42), "Instance2" : A(3.141)}

print(data) 
print( data["Instance1"].value + data["Instance2"].value )

Выход:

{'Instance1':  _42_ , 'Instance2':  _3.141_ }
45.141

Большую часть времени, когда вам нужны сгенерированные пользователем "имена" для переменных, вы должны очень сильно пересмотреть ваши варианты.


(*) Ваш базовый класс не хранит неподтвержденные экземпляры, настоящий диктант предотвратит сбор мусора:

k1 = ResultSeq("A","B")
k2 = ResultSeq("C","D")
k3 = ResultSeq("E","F")

for g in ResultSeq.get_instances():
    print(g.seq1, g.seq2)

k2 = None # no instance of k2 anywhere
k3 = None # no instance of k3 anywhere

для g в ResultSeq.get_instances (): печать (g.seq1, g.seq2)

A B
C D
E F

A B # 2.print loop after removing instances k2,k3

Документация:

https://docs.python.org/3/library/weakref.html
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...