Python 更新类中的所有对象
我对在Python中使用OOP非常陌生。 我有一个问题要解决,我能够部分解决它。对不起,如果我不能把我的问题说清楚的话 如果我为类Python 更新类中的所有对象,python,class,oop,Python,Class,Oop,我对在Python中使用OOP非常陌生。 我有一个问题要解决,我能够部分解决它。对不起,如果我不能把我的问题说清楚的话 如果我为类ClassTest创建一个对象test,然后键入Python test.__dict__ 我将得到以下结果: {'W0': 41.95659301705824, 'right': 'Seq1', 'W1': 86.66314873856487, 'left': <__main__.BranchLength object at 0x1083f8110>}
ClassTest
创建一个对象test
,然后键入Python
test.__dict__
我将得到以下结果:
{'W0': 41.95659301705824, 'right': 'Seq1', 'W1': 86.66314873856487, 'left': <__main__.BranchLength object at 0x1083f8110>}
我将:
{'W0': 86.66314873856487, 'right': 'Seq2', 'W': 41.95659301705824, 'left': <__main__.BranchLength object at 0x1083f8150>}
{'W0':86.66314873856487'右':'Seq2','W':41.95659301705824'左':}
等等
是否有方法以交互方式访问左侧的所有实例(?)
?例如,我对更改W0
的所有值感兴趣
谢谢 我不太确定您想做什么,我必须猜测您的类
TestClass
和分支长度
是什么样子。(在我的示例中,它们是相同的,但在您的代码中肯定不是)
也许你正在寻找这样的东西:
#! /usr/bin/python3
class TestClass:
def __init__ (self, W0, left):
self.W0, self.left = W0, left
def updateW0 (self, f):
self.W0 = f (self.W0)
if self.left and hasattr (self.left, 'updateW0'):
self.left.updateW0 (f)
class BranchLength:
def __init__ (self, W0, left):
self.W0, self.left = W0, left
def updateW0 (self, f):
self.W0 = f (self.W0)
if self.left and hasattr (self.left, 'updateW0'):
self.left.updateW0 (f)
b0 = BranchLength ('branch zero', None)
b1 = BranchLength ('branch one', b0)
b2 = BranchLength ('branch two', b1)
test = TestClass ('the test', b2)
for x in [b0, b1, b2, test]: print (x.W0)
test.updateW0 (lambda x: '{} {}'.format (x, x) ) #whatever update you need
for x in [b0, b1, b2, test]: print (x.W0)
正如其他人所建议的那样,这看起来像是一场灾难 你可能想看看。例如:
class A(object):
def __init__(self, x, child = None):
self.x = x
self.child = child
def increments(self):
self.x += 1 # increment this one
# Check that the child is not 'None' or some other value
if hasattr(self.child, 'increments'):
# recursively increment the child
self.child.increments()
def __repr__(self):
# friendly representation
return 'A(%r, %r)' % (self.x, self.child)
>>> a = A(1, A(2, A(3, A(4))))
>>> a
A(1, A(2, A(3, A(4, None))))
>>> a.increments()
>>> a
A(2, A(3, A(4, A(5, None))))
>>> a.increments()
>>> a
A(3, A(4, A(5, A(6, None))))
基本上,您将递归函数X
定义为:
X
)class Node(object):
def __init__(self, x, *children):
self.x = x
self.children = []
if children:
self.children.extend(children)
def updateLeafs(self, newx):
if self.children:
# This node has children: it is not a Leaf
for c in self.children:
c.updateLeafs(newx)
else:
# This node has no children -> Definition of a leaf !
self.x = newx
def __str__(self):
"Pretty printing of the tree"
if self.children:
# A node
return 'Node(%s -> [%s])' % (repr(self.x), ','.join(str(c) for c in self.children))
else:
# A leaf
return 'Node(%s)' % repr(self.x)
你会得到:
>>> tree = Node(1, Node(4, Node(4, Node(4), Node(5)), Node(6), Node(7, Node(8))))
>>> print tree
Node(1 -> [Node(4 -> [Node(4 -> [Node(4),Node(5)]),Node(6),Node(7 -> [Node(8)])])])
>>> tree.updateLeafs(10)
>>> print tree
Node(1 -> [Node(4 -> [Node(4 -> [Node(10),Node(10)]),Node(10),Node(7 -> [Node(10)])])])
另一种可能是为你的叶子和树枝设置不同的类型:
class Branch(object):
def __init__(self, *children):
self.children = children
def update(self, newx):
for c in self.children:
c.update(newx)
def __str__(self):
"Pretty printing of the tree"
return 'Branch([%s])' % (','.join(str(c) for c in self.children))
class Leaf(object):
def __init__(self, x):
self.x = x
def update(self, newx):
self.x = newx
def __str__(self):
return 'Leaf(%s)' % self.x
这就产生了:
>>> tree = Branch(Branch(Branch(Leaf(4), Leaf(5)), Leaf(6), Branch(Leaf(8))))
>>> print tree
Branch([Branch([Branch([Leaf(4),Leaf(5)]),Leaf(6),Branch([Leaf(8)])])])
>>> tree.update(10)
>>> print tree
Branch([Branch([Branch([Leaf(10),Leaf(10)]),Leaf(10),Branch([Leaf(10)])])])
前者允许动态叶(即,您可以稍后向叶添加新的子项,从而使它们不再是叶),而如果您的树节点和叶本质上不同,则后者更有意义(例如,对于文件系统,叶是文件,树是目录结构)。这实际上取决于你的问题来选择哪一个是最好的。好吧,你有两种可能的解决方案。您可以尝试将
TestClass
类的每个实例都保存在一个列表中,除了现在如何嵌套它们之外,还可以简单地遍历列表,对所有实例执行相同的操作
不过这有点笨重,更好的解决方案可能是从“顶级对象”开始,使用递归遍历树,在运行时操纵每个实例。例如:
def change_attr(tree, target, new_val):
setattr(tree, target, new_val)
# essentially the same as doing `tree.__dict__[target] = new_val`
if tree.left is None:
return
else:
change_attr(tree.left, target, new_val)
然后,通过调用
change_attr(test, 'W0', 'foobar')
…并将其中的每个子分支更新为适当的值。我觉得无论您试图做什么,您都是在错误地进行。你想做什么?你想穿过一棵树吗?也就是说,从某个对象开始,转到其名为
left
的成员,如果该成员又有一个left
成员,则继续下去,继续下去?一种常见的模式是有一个类变量来跟踪所有实例<代码>\uuuu init\uuuuu将向实例添加self
,\uuu del\uuuu
将相应地删除它。现在,访问所有实例是一个简单的循环,只需在实例上进行循环即可!谢谢我想这正是我需要做的。我正在使用一种图形。我需要有类似('A':c,'B':c):B,'c':(c+B)):c,'D':'(c+B+A)的东西。其中a、b和c是浮动的。这是一个模拟。所以首先我会有('A':A,'B':A)。。。。然后我会有(('A':b,'C':b):A,'b':(b+C))。。等等所以我认为你的解决方案会奏效。。。我会努力实现它,我会让你知道!!谢谢很高兴我能帮忙!互联网上有很多关于图形遍历的文档,所以你应该能够找到很多文档。递归更新图形时的主要陷阱是最终进入循环AB,在循环AB中您会得到a更新->B更新->a更新->B更新->。。。但一旦你知道了,就很容易避免:)嗨!你介意解释一下这个“hasattr”到底在做什么吗?我已经搜索了这些信息,但找不到我能理解的答案。在您的示例中:“if hasattr(self.child,'increments')”。self.child是类A中的一个属性,对吗?但“增量”指的是什么?谢谢你好此hasattr
检查其第一个参数是否具有具有给定名称的_attr_ibute。我不直接检查子项的类型(尽管可能),我只检查它是否有增量
方法,然后再调用增量
方法。这称为duck类型()。我没有把自己限制在A
类型的对象上(例如,如果类型(self.child)==A
,我会用递增方法接受任何类型。嗨!谢谢我仍然在增加一些我需要的数字时遇到问题(但我几乎做到了)。想象例如:使用您的示例,想象一下如果您有a=a(1,a(4,a(4,a(4))),并且您只想更新最后一个数字(请注意,我为其他一些子项添加了相同的数字4)。有办法吗?快速有效的方法?我正在研究一个更复杂的例子,但一个孩子的理性应该适用于不止一个孩子,对吗?在我的示例中,对于每个“内部节点”,我有四个属性。再次感谢!
change_attr(test, 'W0', 'foobar')