更新类中的所有对象

2024-04-27 23:32:45 发布

您现在位置:Python中文网/ 问答频道 /正文

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

如果我创建一个类ClassTest的对象test,并用Python键入

test.__dict__

我将得到以下结果:

^{pr2}$

如果我再次输入:

^{3}$

我要:

{'W0': 86.66314873856487, 'right': 'Seq2', 'W': 41.95659301705824, 'left': <__main__.BranchLength object at 0x1083f8150>}

等等。。。在

有没有一种交互访问所有实例的方法是left?例如,我对更改W0的所有值感兴趣。在

谢谢!在


Tags: 对象testright键入objectmainleftdict
3条回答

正如其他人所建议的,这看起来像一个tree (or a graph) traversal。在

您可能需要查看recursive algorithms。例如:

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定义为:

  1. 处理对象的内部状态
  2. 对任何依赖对象(例如其子对象(ren))执行X

编辑

关于只更新最后一个值的最后一条注释(对于树,这称为leaf):有两种解决方案:

一种方法是对所有的图使用相同类型的节点,并将叶定义为“没有子节点的节点”:

^{pr2}$

你会得到:

>>> 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)])])])

前者允许动态叶(也就是说,你可以在以后向leaf添加新的子元素,这样它们就不再是叶子了),而如果你的树节点和叶子本质上不同(例如对于文件系统,你的叶子是文件,树是一个目录结构),那么后者就更有意义了。选择哪一个最好取决于你的问题。在

你有两个可能的解决方案。除了现在如何嵌套它们之外,您可以尝试将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)

然后通过调用将TestClass类的实例传递到函数中

^{pr2}$

…并将其中的每个子分支更新为适当的值。在

我不太确定您要做什么,我必须猜测您的类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)

相关问题 更多 >