Python通过某个属性进行恢复,在属性更改后重新使用

2024-09-27 09:23:44 发布

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

我尝试使用python3.5标准库中的heappq模块来为相同类型的对象建立一个优先级队列。我希望能够基于对象的属性进行修复,然后更改其中一些属性的值,然后根据新值重新进行修复。我在想我该怎么做。在

import heappq
class multiNode:
    def __init__(self, keyValue):
        self.__key = keyValue
    def setKey(self, keyValue):
        self.__key = keyValue
    def getKey(self):
        return self.__key

queue = [multiNode(1), multiNode(2), multiNode(3)]
heapq.heapify(queue) #want to heapify by whatever getKey returns for each node
queue[0].setKey(1000)
heapq.heapify(queue) #re heapify with those new values

Tags: 模块对象keyself标准属性queuedef
2条回答

有多种方法可以使代码工作。例如,您可以通过实现一些rich comparison operator methods(也许可以使用^{}来实现其余的)来使您的项可排序:

@functools.total_ordering
class multiNode:
    def __init__(self, keyValue):
        self.__key = keyValue
    def setKey(self, keyValue):
        self.__key = keyValue
    def getKey(self):
        return self.__key
    def __eq__(self, other):
        if not isinstance(other, multiNode):
            return NotImplemented
        return self.__key == other.__key
    def __lt__(self, other):
        if not isinstance(other, multiNode):
            return NotImplemented
        return self.__key < other.__key

这将使您的代码正常工作,但在每次更改队列中的某个节点时,尤其是在队列中有很多节点的情况下,重新初始化队列可能不是很有效。一个更好的方法可能是在队列周围编写一些额外的逻辑,这样就可以使队列条目无效,而不会删除它或违反heap属性。然后,当您有一个需要更新的项时,您只需使它的旧条目无效,并添加一个具有新优先级的新条目。在

下面是一个快速而肮脏的实现,它使用字典将节点实例映射到[pritority, node]列表。如果节点正在更新其优先级,则检查字典并将列表的node部分设置为None。当从队列前面弹出节点时,将忽略无效的条目。在

^{pr2}$

您可能需要在重新确认时对此进行测试,以确定程序实际使用队列的速度更快。在

关于您的multiNode类的最后几点注释(与您在问题中所问的内容无关):

你在课堂上做的很多事情都不是很像Python。首先,Python最常见的命名约定是将CapitalizedNames用于类,lower_case_names_with_underscores用于几乎所有其他东西(各种变量、函数、模块)。在

__key使用双前导下划线的另一个问题。双前导(而不是尾随)undescrores调用Python的名称混乱系统。这看起来似乎是为了让变量私有化,但实际上并非如此。它更倾向于帮助防止意外的名称冲突,例如在代理对象(在其他情况下模仿其他对象的属性)或mixin类(可能由具有未知属性的其他类型继承)中设置属性时。如果类外的代码确实想访问您的multiNode类中损坏的属性__key,那么它们仍然可以通过使用_multiNode__key来实现。要暗示某个有意为私有属性,您只需使用一个下划线_key。在

这让我想到了我的最后一期,那key可能根本不应该是私人的。使用getXsetX方法修改私有实例变量并不是很像python。更常见的做法是记录属性是类的公共API的一部分,并让其他代码直接访问它。如果以后决定在查找或修改属性时需要执行一些特别的操作,可以使用property描述符自动将属性访问转换为对getter和setter函数的调用。其他编程语言通常以getter和setter开始,而不是公共属性,因为以后没有这种方法可以更改属性API的实现。所以不管怎样,我会让你的类的__init__只设置self.key = keyValue并完全删除{}和{}!在

一种简单的方法是使用dicts和Python内置的id()方法。这个方法基本上允许您将堆作为您创建的对象的id的堆,然后通过在dict中访问它们来更新这些对象,其中它们的id是键。我在我的本地机器上试过了,它似乎能满足您的要求:

import heapq
class multiNode:
    def __init__(self, keyValue):
        self.__key = keyValue
    def setKey(self, keyValue):
        self.__key = keyValue
    def getKey(self):
        return self.__key

first_node = multiNode(1)
second_node = multiNode(2)
thrid_node = multiNode(3)
# add more nodes here
q = [id(first_node), id(second_node), id(third_node)]
mutilNode_dict = {
    id(first_node): first_node,
    id(second_node): second_node,
    id(third_node): third_node
}
heapq.heapify(q)
multiNode_dict[q[0]].setKey(1000)
heapq.heapify(q)

heapify()在这里不会做太多,因为对象的id在被删除之前都是相同的。如果要向堆中添加新对象并取出对象,则此方法更有用。在

相关问题 更多 >

    热门问题