【问题标题】:How to keep variable and dictionary that contains it consistent?如何保持变量和包含它的字典一致?
【发布时间】:2016-04-29 04:18:58
【问题描述】:

我有一个变量

self.foo = 1

还有一本字典

self.foo_dict = {
    'foo_key' = self.foo
}

我希望能够更改self.foo 的值,并使其也更改为self.foo_dict。如果这是在 C 中(并且 dict 是一个结构),我将只使用一个指针。

有什么建议吗?这在 Python 中是否可行?

【问题讨论】:

  • Python equivalent of pointers 的可能重复项。您可以创建一个包装类,并使用该类的对象,而不是使用 int 作为 foo 的值。

标签: python-3.x


【解决方案1】:

不需要包装类!
只需将self.foo 设为访问字典中值的属性即可:

class Bar:
    def __init__(self, foo_):
        self.foo_dict = {}  
        self.foo = foo_

    @property
    def foo(self):
        return self.foo_dict["foo_key"]

    @foo.setter
    def foo(self, value):
        self.foo_dict["foo_key"] = value

    def show(self):
        print("foo={} ; foo_dict['foo_key']={}".format(
                        self.foo, self.foo_dict["foo_key"]))

b = Bar(1)
b.show()
b.foo = 2
b.show()
b.foo_dict["foo_key"] = 3
b.show()

See this code running on ideone.com

属性看起来像普通的实例成员字段,但它们实际上是可以做任何事情的自定义函数。这样在访问foo 属性时会调用两个foo(...) 方法。用@property 装饰的那个是getter,用@PROPERTYNAME.setter 装饰的那个显然是setter。您还可以通过简单地省略其中一种属性方法来限制对该属性的读取或写入访问。

在这里,他们将所有操作重定向到字典。这样一来,您就只有一个简单可变变量的实例,但可以通过多种方式访问​​它。

上面的例子会产生这样的输出:

foo=1 ; foo_dict['foo_key']=1
foo=2 ; foo_dict['foo_key']=2
foo=3 ; foo_dict['foo_key']=3

所以我们可以看到,无论是通过字典还是通过属性改变值,两个名字总是指向同一个变量。

【讨论】:

  • +1 用于属性方法。在我发布我的第一个答案之后,我也想这样做。但是,你的第一句话让我觉得……有点紧张,你懂我的意思吗? ;-)
  • :D 谢谢。但是,如果我们有一个更舒适的选项,所有同步都在后面自动完成并且我们没有任何接口更改,那为什么还要麻烦额外的包装类和调用方法来获取和设置其中的值......
  • 我同意你的方法更好。就像我说的那样,在我发布了我的第一个答案之后,我认为它也可以使用属性来完成。但后来我决定不改变我的第一个答案。毕竟,如果我也添加了属性方法,您将没有机会在这里发布答案;-)
  • @ByteCommander 不错的答案。我觉得有点奇怪。据我所知,在写b.foo的时候,必须调用getter方法。那么为什么我收到变量 self.foo 的值而不是您在 getter 方法中返回的字典(即 foo(self))?
  • @EbraHim foo 是一个属性,这意味着在外部它就像一个普通的实例成员,就像我在任何地方用self.foo = 1 初始化它一样,例如在构造方法中。但在内部,它是一对两个函数,一个 getter 和一个 setter,当您访问该属性时会被隐式调用。 @property | def foo(self): 方法是 getter,它在字典 foo_dict 中查找映射到“foo_key”的值。那是存储值的地方。 @foo.setter | def foo(self, value): 方法是设置器,它将新的value 存储在带有“foo_key”的foo_dict 中。
【解决方案2】:

这在 Python 中是否可行?

答案 1:不是直截了当,因为int 是不可变的。不过……

答案 2:有一些变通方法可以实现您想要的。

您需要为foo 提供一个包装器 类,而不是使用int 作为变量int,因为int 是不可变的,并且任何包装器 em> 你定义的类不是。

foo 的包装类:

class Foo:
    def __init__(self, val):
        self.foo = val
    def set(self, val):
        self.foo = val
    def __repr__(self):
        return str(self.foo)

那么,您拥有一致的变量-字典对的类可能是这样的:

class A:
    def __init__(self):
        self.foo = Foo(1)
        self.foo_dict = {
            'foo_key': self.foo
            }
    def set_foo(self, newval):
        self.foo.set(newval)

试运行:

>>> a = A()
>>> a.foo
1
>>> a.foo_dict['foo_key']
1
>>> a.set_foo(20)
>>> a.foo
20
>>> a.foo_dict['foo_key']
20

【讨论】:

  • 你为什么不简单地使用一个类?
  • @EbraHim 因为二类是这种情况的明显解决方案。
  • 我发了一个临时答案,请问你看一下吗?
【解决方案3】:
>>> class Test(object):
    def __init__(self,foo):
        self.foo = foo
        self.foo_dict = {'foo_key': foo}
    def set_foo(self, foo):
        self.foo = foo
        self.foo_dict['foo_key'] = foo


>>> a = Test(1)
>>> a.foo
1
>>> a.foo_dict
{'foo_key': 1}
>>> a.set_foo(2)
>>> a.foo
2
>>> a.foo_dict
{'foo_key': 2}
>>> 

【讨论】:

    【解决方案4】:

    我没有完全理解你的问题,但是如果你想改变self.foo 的值,你可以直接使用字典来完成。假设你有一些字典:

    self.some_dict = {"valueA":1}
    

    考虑到字典的功能是由keyvalue 对,您可以像这样更改valueA 的值:

    self.some_dict["valueA"] = some_value
    

    因此,键的值更改为some_value。作为另一种可能性,您可以使用dict.copy 创建字典的副本。有了这个,你就有了另一个字典,它的值与第一个字典相同,然后用 dict.update 更新以在键中添加新元素或值。像这样的:

    self.some_dict = {"value1":1}
    self.other_dict = some_dict
    self.other_dict.update("{"value2": 2}")
    

    有了这个,您可以将value2 更新为 other_dict。

    【讨论】:

    • 哇哇哇,打字的时候慢下来,好吗!你的写作中有太多的拼写错误。而且我不认为你已经很好地理解了这个问题。
    猜你喜欢
    • 1970-01-01
    • 2012-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-17
    • 2022-11-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多