0

我有一个定义自己的类,__getattr__()以便与实例化对象包含的 XML 树进行交互。这对用户隐藏了 XML 结构,并允许他设置标签值等,就好像它们是对象上的普通字段一样,并且适用于所有字段,除了一个:名为field. 这是它的外观:

>>> q = MyQuery()
>>> q.file = "database"
>>> print(q)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<requestCollection xmlns="http://dwd.de/sky">
  <read>
    <select>
      <referenceDate>
        <value></value>
      </referenceDate>
    </select>
    <transfer>
      <file name="my file"/>
    </transfer>
  </read>
</requestCollection>
>>> q.file

效果很好,应该发生的副作用就是这样做的。但是如果我尝试设置 field field,我会得到一个方法不应该返回的字符串。为清楚起见,这是 my 的简化版本__getattr__

def __getattr__(self, key):
    logging.info("Looking up value for key {}.".format(key))
    if key == "something"
        return self.method_with_side_effect(key)
    if key in field_list:
        logging.info("Key is in the field list.")
        return self.other_method_with_side_effects(key)

ensemble_member并且field都在field_list. 看一下这个:

>>> q = MyQuery()
>>> q.ensemble_member
Looking up value for key __members__.
Looking up value for key __methods__.
Looking up value for key ensemble_member.
Key is in the field list.
... Side effects ...
>>> q.field
'station'
Looking up value for key __members__.
Looking up value for key __methods__.

for 的行为ensemble_member是正确field的,因为它完全不正确。这是为什么?

我没有方法,也没有名为field.

另一个有趣的事情是,如果我把它放在第一行__getattr__

def __getattr__(self, key):
    if key == "field":
        raise ValueError

仍然会发生以下情况:

>>> q = MyQuery()
>>> q.field
'station'
Looking up value for key __members__.
Looking up value for key __methods__.

这是怎么回事?

4

1 回答 1

1

我明白了——最终,有问题的代码是以下几行:

class SkyQuery(object):
    _unique_fields = ["parameter",
                      "ensemble",
                      "forecast",
                      "station"]
    _field_tag_values = [field + "_value" for field in _unique_fields]

在我的列表理解中命名临时变量“字段”导致了问题。在我完成后,Python 保留了它。这种行为是一致的,我只是没想到。

我在这里看到了三种解决方案(第三种是 user4815162342 建议的)。我实施了第三个。

  1. 将临时变量重命名为x而不是field. 然后我的代码中仍然有x一个临时变量,但是因为不应该调用任何成员,x所以它不会打扰我。

  2. 调用del(field)删除字段。我不喜欢调用del(),我认为它会使我的代码混乱,但如果我以后真的需要能够访问该变量,它会起作用。

  3. list(field + "_value" for field in _unique_fields)用不存在此问题的生成器表达式替换列表推导

于 2013-05-21T13:01:26.513 回答