【问题标题】:Python change dict value [duplicate]Python更改dict值[重复]
【发布时间】:2021-10-17 15:05:57
【问题描述】:

我创建了一个带有字典变量的类,以及一个编辑它的方法:

class Test:
   TestDict = {"TestKey": "OldValue"}

   def ChangeDictionary(self):
       self.TestDict["TestKey"] = "NewValue"

然后,我创建了两个对象:

ObjectOne = Test()
ObjectTwo = Test()

在 ChangeDictionary 方法调用之前和之后打印他们的字典:

# Print values before method call
print(ObjectOne.TestDict)
print(ObjectTwo.TestDict)

# Call method
ObjectTwo.ChangeDictionary()

# Print values after method call
print(ObjectOne.TestDict)
print(ObjectTwo.TestDict)

我得到这个输出:

{'TestKey': 'OldValue'}
{'TestKey': 'OldValue'}
    * * Method call * *
{'TestKey': 'NewValue'}
{'TestKey': 'NewValue'}

因此,从第二个对象调用的 ChangeDictionary 方法也更改了值,并且在第一个对象中也发生了更改。
是 Python 语言错误还是其他地方的原因?

更新: 如果类变量是任何其他类型(例如 - 字符串) - 在第一个对象变量中将具有旧值:

class Test:
    TestString = "OldValue"

    def ChangeString(self):
        self.TestString = "OldValue"

【问题讨论】:

  • @tevemadar 如果我做对了 - 不。在您发布的链接的主题中,讨论了从对象更改类的变量。我的问题是为什么在我从其他对象(同一类的实例)调用方法后对象的字典值会发生变化,如果我将变量类型更改为任何其他(例如字符串)值将保持不同。
  • TestDict 被所有对象共享,因为它没有在__init__ 中定义。要解决此问题,请创建一个 self.TestDict 并在 __init__ 函数中对其进行初始化。详情请查看我的回答。
  • 如果它有助于解决您的问题,请标记答案:)
  • @AkshaySehgal 但为什么它只适用于字典?如果变量将具有字符串类型,则在我更改它之后 - 第一个对象将具有旧值。
  • “它是 Python 语言错误”这不应该是你第一次喜欢这样的东西,几乎可以肯定,你只是不理解一些东西

标签: python python-3.x dictionary methods


【解决方案1】:

正如上面定义的answer

  • init 方法之外的元素是静态元素;他们属于这个班级。
  • init 方法中的元素是对象(self)的元素;他们不属于这个班级。

要解决这个问题,试试这个 -

class Test:
    def __init__(self):                          #<-------
        self.TestDict = {"TestKey": "OldValue"}  #<-------
    
    def ChangeDictionary(self):
        self.TestDict["TestKey"] = "NewValue"
        
        
ObjectOne = Test()
ObjectTwo = Test()

# Print values before method call
print(ObjectOne.TestDict)
print(ObjectTwo.TestDict)

# Call method
ObjectTwo.ChangeDictionary()
print("** Method call **")

# Print values after method call
print(ObjectOne.TestDict)
print(ObjectTwo.TestDict)
{'TestKey': 'OldValue'}
{'TestKey': 'OldValue'}
** Method call **
{'TestKey': 'OldValue'}
{'TestKey': 'NewValue'}

编辑:正如@juanpa.arrivillaga 所提到的,您对类函数所做的修改是定义一个与您之前的对象不同的不可变对象。

注意以下两种方法的不同-

#### ORIGINAL STRING ####

class Test:
    TestString = "OldValue"

    def ChangeString(self):
        self.TestString = "NewValue"
        
        
ObjectOne = Test()
ObjectTwo = Test()

# Print values before method call
print(ObjectOne.TestString)
print(ObjectTwo.TestString)

# Call method
ObjectTwo.ChangeString()
print("** Method call **")

# Print values after method call
print(ObjectOne.TestString)
print(ObjectTwo.TestString)

print("** Self dicts **")
print(ObjectOne.__dict__)
print(ObjectTwo.__dict__)
OldValue
OldValue

** Method call **
OldValue
NewValue

** Self dicts **
{}
{'TestString': 'NewValue'}

与,__init__


### FIXED STRING ###

class Test:
    def __init__(self):
        self.TestString = 'OldValue'
    
    def ChangeString(self):
        self.TestString = "NewValue"
               
ObjectOne = Test()
ObjectTwo = Test()

# Print values before method call
print(ObjectOne.TestString)
print(ObjectTwo.TestString)

# Call method
ObjectTwo.ChangeString()
print("** Method call **")

# Print values after method call
print(ObjectOne.TestString)
print(ObjectTwo.TestString)

print("** Self dicts **")
print(ObjectOne.__dict__)
print(ObjectTwo.__dict__)
OldValue
OldValue
** Method call **
OldValue
NewValue
** Self dicts **
{'TestString': 'OldValue'}
{'TestString': 'NewValue'}

【讨论】:

  • 谢谢,但为什么它只适用于字典类型变量?如果变量将是一个字符串 - 即使他们将定义 ouside init - 他们只会在他们的对象中改变。
  • "__init__ 之外的变量集属于该类。"不完全是。在类块中设置的变量属于类。实例变量是您分配给实例的任何属性。
  • @KompTip 不,他们不会。 str 对象是不可变的,所以你不能改变它们。您可能在您的方法中分配另一个字符串,这会影响您的类变量
  • @juanpa.arrivillaga,更新了语言并添加了参考。
  • @KompTip 不,对象的类型无关。如果您在方法中将变量分配给self,即第一个位置参数的值,则将属性分配给实例。考虑像@​​987654332@ 这样的东西,然后如果你这样做foo = Foo(); foo.bar = 42 那么你创建了一个实例变量。这与方法中发生的完全相同def some_method(self): self.bar = 42self 只是一种命名约定,当您在实例上调用 some_method 时,实例本身作为第一个传递论据\
猜你喜欢
  • 2011-03-25
  • 2020-03-01
  • 2013-05-22
  • 1970-01-01
  • 2013-02-15
  • 2022-07-13
  • 1970-01-01
  • 2021-12-26
相关资源
最近更新 更多