如何正确使用__setitem__?

How to use __setitem__ properly?

我想做一个数据对象:

class GameData:
  def __init__(self, data={}):
    self.data = data

  def __getitem__(self, item):
    return self.data[item]

  def __setitem__(self, key, value):
    self.data[key] = value

  def __getattr__(self, item):
    return self.data[item]

  def __setattr__(self, key, value):
    self.data[kay] = value

  def __repr__(self):
    return str(self.data)

当我创建一个 GameData 对象时,我得到了 RecursionError。我怎样才能避免 setitem 召回自己?

在赋值 self.data = data 中,调用 __setattr__ 是因为 self 目前没有名为 data 的属性。 __setattr__ 然后调用 __getattr__ 来获取不存在的属性 data__getattr__ 本身再次调用 __getattr__。这是一个递归。

执行__setattr__时使用object.__setattr__(self, 'data', data)赋值。

class GameData:
  def __init__(self, data=None):
    object.__setattr__(self, 'data', {} if data is None else data)

  def __getitem__(self, item):
    return self.data[item]

  def __setitem__(self, key, value):
    self.data[key] = value

  def __getattr__(self, item):
    return self.data[item]

  def __setattr__(self, key, value):
    self.data[key] = value

  def __repr__(self):
    return str(self.data)

详情见the __getattr__ manual

另外,不要使用可变对象作为默认参数,因为默认参数中的同一个对象 {}GameData 个实例之间共享。