【问题标题】:Save changes of state for custom class instances in Python在 Python 中保存自定义类实例的状态更改
【发布时间】:2018-08-12 06:33:37
【问题描述】:

我很难弄清楚为什么我的print(Node(3).value) 正在打印0。有什么想法吗?

当我运行这段代码时,我得到了

First: 6 Value: 8 Children: [9]
First: 8 Value: 23 Children: [9]
First: 3 Value: 3 Children: [5]
First: 6 Value: 8 Children: [7]
First: 4 Value: 20 Children: [8]
First: 1 Value: 17 Children: [8]
First: 8 Value: 23 Children: [10]
First: 5 Value: 11 Children: [8]
First: 1 Value: 17 Children: [2]
0

有什么想法吗?我知道我没有将节点保存在任何地方,但我的思绪无法绕开它。 任何帮助将不胜感激,谢谢!

# Complete the primeQuery function below.
n = 10
first = [6, 8, 3, 6, 4, 1, 8, 5, 1]
second = [9, 9, 5, 7, 8, 8, 10, 8, 2]
values = [17, 29, 3, 20, 11, 8, 3, 23, 5, 15]
queries = [1, 8, 9, 6, 4, 3]


class Node(object):
    def __init__(self, data, value=0):
        self.data = data
        self.value = value
        self.children = []

    def addChild(self, child):
        self.children.append(child)

    def setValue(self, givenV):
        self.value = givenV


def primeQuery(n, first, second, values, queries):
    i = 0
    while i < n - 1:
        f = Node(first[i], values[first[i] - 1])

        s = Node(second[i], values[second[i] - 1])

        f.addChild(s.data)

        print(f"First: {f.data} Value: {f.value} Children: {f.children}")

        i += 1

    print(Node(3).value)


primeQuery(n, first, second, values, queries)

【问题讨论】:

  • 你没有保存你的Node对象f & s
  • Node(3) 将创建一个带有value = 0Node
  • @AzatIbrakov,哦,呵呵!嗯,但我对如何实际保存它们有点困惑?
  • @KlausD。 ,是的,看到我的代码是有道理的。但是有没有关于如何保存对象的示例 sn-p?
  • 这取决于您要构建的数据结构

标签: python python-3.x tree


【解决方案1】:

声明

Node(3).value

创建Node 对象,其中data 设置为3value 设置为0(默认参数),所以当你得到它的value 时,它会返回0

如果您想创建 Node 对象然后重新使用它们 - 您应该将它们存储在某种容器中。

假设

  • data 字段是Node 的可哈希唯一标识符,
  • 如果 Node 已创建并且我们传递不同的 value -- 旧的 value 仍然存在

我在这里看到至少 2 种方法:

  • 在顶层创建容器,在创建时显式添加Nodes 并在之后使用它访问它们

    def primeQuery(n, first, second, values, queries):
        i = 0
        # top-level container of ``Node``s
        nodes = {}
    
        def get_or_create_node(data, value):
            try:
                # trying to access already created ``Node``
                result = nodes[data]
            except KeyError:
                # no ``Node`` found, create it...
                result = Node(data, value)
                # ... and register
                nodes[data] = result
            return result
    
        while i < n - 1:
            f = get_or_create_node(first[i], values[first[i] - 1])
            s = get_or_create_node(second[i], values[second[i] - 1])
    
            f.addChild(s.data)
    
            print(f"First: {f.data} Value: {f.value} Children: {f.children}")
    
            i += 1
    
        print(nodes[3].value)
        # we can return ``nodes`` here if we want to use them outside of given function
    

    给我们

    First: 6 Value: 8 Children: [9]
    First: 8 Value: 23 Children: [9]
    First: 3 Value: 3 Children: [5]
    First: 6 Value: 8 Children: [9, 7]
    First: 4 Value: 20 Children: [8]
    First: 1 Value: 17 Children: [8]
    First: 8 Value: 23 Children: [9, 10]
    First: 5 Value: 11 Children: [8]
    First: 1 Value: 17 Children: [8, 2]
    3
    
  • 先前方法的扩展:使用缓存已创建的全局函数来限制Nodes 的创建:

    # in module namespace
    def get_or_create_node(data, value=0,
                           *,
                           # hack, see **note**
                           cache={}):
        # we've moved class definition inside of a function to restrict its instances creation
        class Node(object):
            def __init__(self, data, value):
                self.data = data
                self.value = value
                self.children = []
    
            def addChild(self, child):
                self.children.append(child)
    
            def setValue(self, givenV):
                self.value = givenV
    
        try:
            result = cache[data]
        except KeyError:
            result = Node(data, value)
            cache[data] = result
        return result
    

    注意:这里我们使用带有可变默认参数的“hack”,更多信息可以在this thread中找到)

    那么当我们需要创建/访问Node对象时——我们应该只使用这个函数

    def primeQuery(n, first, second, values, queries):
        i = 0
        while i < n - 1:
            f = get_or_create_node(first[i], values[first[i] - 1])
            s = get_or_create_node(second[i], values[second[i] - 1])
    
            f.addChild(s.data)
    
            print(f"First: {f.data} Value: {f.value} Children: {f.children}")
    
            i += 1
    
        print(get_or_create_node(3).value)
    

    这将为我们提供与以前相同的输出。

进一步改进

改变value

如果我们关于value 持久化的假设被证明是错误的——我们可以简单地添加对value 的更改,如果它像这样传递:

  • 第一种方法:

    def get_or_create_node(data, value):
        try:
            # trying to access already created ``Node``
            result = nodes[data]
        except KeyError:
            # no ``Node`` found, create it...
            result = Node(data, value)
            # ... and register
            nodes[data] = result
        # adding ``else``-clause
        else:
            result.setValue(value)
        return result
    
  • 在第二种方法中:将value参数的默认值设置为None并检查它是否被指定为

    def get_or_create_node(data, value=None,
                           *,
                           cache={}):
        class Node(object):
            def __init__(self, data, value):
                self.data = data
                self.value = value
                self.children = []
    
            def addChild(self, child):
                self.children.append(child)
    
            def setValue(self, givenV):
                self.value = givenV
    
        try:
            result = cache[data]
        except KeyError:
            if value is None:
                # default value
                value = 0
            result = Node(data, value)
            cache[data] = result
        else:
            if value is not None:
                result.setValue(value)
        return result
    

继承自object

如果我们在 Python 3 中工作 -- 不需要将 object 指定为基类,它会默认设置(参见 this thread),所以不是

class Node(object):
    ...

我们可以简单地写

class Node:
    ...

使用for-loop 代替while

当我们有for-loop 和range 对象时,我们不需要手动使用while-loop 和递增i,所以不是

i = 0
while i < n - 1:
    ...
    i += 1

我们可以写

for i in range(n - 1):
    ...

我也认为这是一个错字,因为我们跳过了 i 等于 n - 1 的大小写,所以我们可以修复它:

for i in range(n):
    ...

最后我们可以看到,当我们可以使用zip built-in & 迭代成对的first & second lists 元素时,i 索引中就不需要了

for first_data, second_data in zip(first, second):
    f = get_or_create_node(first_data, values[first_data - 1])
    s = get_or_create_node(second_data, values[second_data - 1])

    f.addChild(s.data)

    print(f"First: {f.data} Value: {f.value} Children: {f.children}")

【讨论】:

    猜你喜欢
    • 2011-03-14
    • 2011-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-29
    • 2015-09-22
    相关资源
    最近更新 更多