首先我应该说我使用的是Python 3.5.2。 当我定义自己的类时,我认为 ipython 出了问题。 因此,当我在标准python控制台中运行以下代码时,我没有收到任何错误:
class A(dict):
def __getattribute__(self, item):
return self[item]
a = A({'x' : 1})
a['x']
但是当我在 ipython 控制台中运行上面的代码时,我收到以下错误:
KeyError Traceback (most recent call last)
/usr/local/lib/python3.5/dist-packages/IPython/core/prefilter.py in prefilter_lines(self, lines, continue_prompt)
333 for lnum, line in enumerate(llines) ])
334 else:
--> 335 out = self.prefilter_line(llines[0], continue_prompt)
336
337 return out
/usr/local/lib/python3.5/dist-packages/IPython/core/prefilter.py in prefilter_line(self, line, continue_prompt)
308 return normal_handler.handle(line_info)
309
--> 310 prefiltered = self.prefilter_line_info(line_info)
311 # print "prefiltered line: %r" % prefiltered
312 return prefiltered
/usr/local/lib/python3.5/dist-packages/IPython/core/prefilter.py in prefilter_line_info(self, line_info)
250 """
251 # print "prefilter_line_info: ", line_info
--> 252 handler = self.find_handler(line_info)
253 return handler.handle(line_info)
254
/usr/local/lib/python3.5/dist-packages/IPython/core/prefilter.py in find_handler(self, line_info)
257 for checker in self.checkers:
258 if checker.enabled:
--> 259 handler = checker.check(line_info)
260 if handler:
261 return handler
/usr/local/lib/python3.5/dist-packages/IPython/core/prefilter.py in check(self, line_info)
414 def check(self, line_info):
415 obj = self.shell.user_ns.get(line_info.ifun)
--> 416 if isinstance(obj, Macro):
417 return self.prefilter_manager.get_handler_by_name('macro')
418 else:
<ipython-input-1-cb6806333b6b> in __getattribute__(self, item)
1 class A(dict):
2 def __getattribute__(self, item):
----> 3 return self[item]
4
KeyError: '__class__'
如果您对此问题有任何疑问,请提供帮助。
答案 0 :(得分:2)
看起来IPython正试图访问a.__class__
,但失败了。它可能是作为诊断目的的某种标准物体扫描。如果您尝试print(a.__class__)
,则在常规Python控制台中会出现相同的错误。
如果词典中没有与该键匹配的条目,则__getattribute__
应该有后备。 the documentation建议在需要访问实际属性时调用基类“__getattribute__
方法”。类似的东西:
class A(dict):
def __getattribute__(self, item):
if item in self:
return self[item]
else:
return object.__getattribute__(self, item)
#or possibly:
#return super().__getattribute__(item)
#... Depending on one's interpretation of "base class"
a = A({'x' : 1})
a['x']
print(a.__class__)
覆盖__getattr__
代替__getattribute__
也可能有意义。这样,仍然可以访问对象的所有属性,而无需在函数中对它们进行任何显式检查。
class A(dict):
def __getattr__(self, item):
if item in self:
return self[item]
else:
raise AttributeError
a = A({'x' : 1})
a['x']
print(a.__class__)