如何在递归中生成 class 的新实例
How to generate a new instance of a class in recursion
最近在学习序列比对算法。得到对齐矩阵后,我可以找到一个最优路径,但是我在寻找多个最优路径(回溯)时遇到了麻烦!
我的想法是用多个实例存储多条路径的结果,最后循环遍历基class的所有实例得到答案。
我知道以下条件:
- 什么条件退出递归
- 什么时候需要创建新实例,什么时候不需要创建?
但是问题出在第二种情况。不知道有多少最优结果,也不知道会产生多少新实例
所以我希望能够动态生成一个带有变量的实例名。
我不知道怎么做:
# those equivalent to new_instance_name = ResultSeq()
a="new_instance_name"
create_new_instance(a,ResultSeq)
我的结果基class是ResultSeq:
class KeepRefs(object):
"""
reference:
"""
__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)
这只是我的解决方案之一。如果有更好的建议,我会很乐意采纳,谢谢!
您不需要 names 来存储变量 - 您可以使用一个简单的列表来存储您的实例:
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
大多数时候,当您需要用户生成 "names" 变量时,您应该非常强烈地重新考虑您的选择。
(*) 您的基类不会保留 non-referenced 个实例,真正的字典会阻止垃圾收集:
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
对于 ResultSeq.get_instances() 中的 g:
打印(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
最近在学习序列比对算法。得到对齐矩阵后,我可以找到一个最优路径,但是我在寻找多个最优路径(回溯)时遇到了麻烦!
我的想法是用多个实例存储多条路径的结果,最后循环遍历基class的所有实例得到答案。 我知道以下条件:
- 什么条件退出递归
- 什么时候需要创建新实例,什么时候不需要创建?
但是问题出在第二种情况。不知道有多少最优结果,也不知道会产生多少新实例
所以我希望能够动态生成一个带有变量的实例名。
我不知道怎么做:
# those equivalent to new_instance_name = ResultSeq()
a="new_instance_name"
create_new_instance(a,ResultSeq)
我的结果基class是ResultSeq:
class KeepRefs(object):
"""
reference:
"""
__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)
这只是我的解决方案之一。如果有更好的建议,我会很乐意采纳,谢谢!
您不需要 names 来存储变量 - 您可以使用一个简单的列表来存储您的实例:
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
大多数时候,当您需要用户生成 "names" 变量时,您应该非常强烈地重新考虑您的选择。
(*) 您的基类不会保留 non-referenced 个实例,真正的字典会阻止垃圾收集:
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
对于 ResultSeq.get_instances() 中的 g: 打印(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