Python 更新类中的所有对象

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>}

我对在Python中使用OOP非常陌生。 我有一个问题要解决,我能够部分解决它。对不起,如果我不能把我的问题说清楚的话

如果我为类
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
定义为:

  • 对对象的内部状态执行某些操作
  • 对任何从属对象(例如其子对象(ren))执行
    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')