为什么Python要查找_成员而不是请求的字段?

为什么Python要查找_成员而不是请求的字段?,python,getattr,Python,Getattr,我有一个类,它定义自己的\uuuu getattr\uuuu(),以便与包含的XML树实例化对象进行交互。这会对用户隐藏XML结构,并允许用户设置标记值等,就好像它们是对象上的普通字段一样,对除一个字段以外的所有字段都有效:名为字段的字段。下面是它的外观: >>> q = MyQuery() >>> q.file = "database" >>> print(q) <?xml version="1.0" encoding="UTF-8"

我有一个类,它定义自己的
\uuuu getattr\uuuu()
,以便与包含的XML树实例化对象进行交互。这会对用户隐藏XML结构,并允许用户设置标记值等,就好像它们是对象上的普通字段一样,对除一个字段以外的所有字段都有效:名为
字段的字段
。下面是它的外观:

>>> 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
集合成员
字段
都在
字段列表
中。看看这个:

>>> 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__.
集合成员
的行为是正确的,而
字段
的行为是完全错误的。为什么呢

我没有名为
字段
的方法或类/对象成员

另一件有趣的事情是,如果我把它放在
\uu getattr\uuu
的第一行:

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)
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__.

发生了什么事?

我明白了-令人不快的代码最后是以下几行:

class SkyQuery(object):
    _unique_fields = ["parameter",
                      "ensemble",
                      "forecast",
                      "station"]
    _field_tag_values = [field + "_value" for field in _unique_fields]
在我的列表理解中命名临时变量“field”是导致问题的原因。Python在我完成后保留了它。这种行为是一贯的,我只是没料到

我在这里看到三种解决方案(第三种是由用户4815162342提出的)。我实现了第三个

  • 将临时变量重命名为
    x
    ,而不是
    字段
    。然后我仍然有
    x
    作为一个临时变量在我的代码中浮动,但是因为不应该调用
    x
    成员,所以我不会感到困扰

  • 调用
    del(字段)
    删除字段。我不喜欢调用
    del()

  • 将列表理解替换为一个生成器表达式
    list(字段+“\u值”表示“唯一”字段中的字段)
    ,该表达式不存在此问题


  • 请发布一个小的可运行示例来演示这个问题。另外,您使用的是哪一版本的Python?您是否在某处调用了
    dir(q)
    ?我没有在任何地方调用dir(q),尽管我只是尝试了一下,其中有“field”。我不知道它是怎么到那里的,我快速地看了一眼;我认为您应该尝试通过删除与问题无关的代码来隔离问题。将列表理解替换为一个生成器表达式
    list(字段+“\u值”表示“唯一”字段中的字段)
    ,该表达式不存在此问题