我有一个类定义了自己的__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
,我会得到一个该方法不应该返回的字符串。为清楚起见,这是我的__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__.
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__.
发生了什么事?
答案 0 :(得分:1)
我已经得到了 - 最终的违规行为是这些行:
class SkyQuery(object):
_unique_fields = ["parameter",
"ensemble",
"forecast",
"station"]
_field_tag_values = [field + "_value" for field in _unique_fields]
在列表推导中命名临时变量“field”导致了问题。完成后,Python保留了它。这种行为是一致的,我只是没想到它。
我在这里看到三个解决方案(第三个是由user4815162342建议的)。我实施了第三个。
将临时变量重命名为x
而不是field
。然后我仍然将x
作为临时变量在我的代码中浮动,但是因为没有成员应该被调用x
它不会打扰我。
致电del(field)
删除该字段。我不喜欢调用del()
,我认为它会使我的代码变得混乱,但如果我真的需要以后能够访问该变量,它会起作用。
将列表推导替换为不共享此问题的生成器表达式list(field + "_value" for field in _unique_fields)