我是 MongoDB 的一个简单数据库层(受minimongo启发)的作者——而且目前几乎绝对是唯一的用户,如果在多个项目中,称为kale
. 我目前__getattr__
在模型基类中的使用导致了一些难以跟踪的错误。
我遇到的问题是去年 6 月 David Halter 在这个网站上简明扼要地阐述的。讨论很有趣,但没有提供任何解决方案。
简而言之:
>>> class A(object):
... @property
... def a(self):
... print "We're here -> attribute lookup found 'a' in one of the usual places!"
... raise AttributeError
... return "a"
...
... def __getattr__(self, name):
... print "We're here -> attribute lookup has not found the attribute in the usual places!"
... print('attr: ', name)
... return "not a"
...
>>> print(A().a)
We're here -> attribute lookup found 'a' in one of the usual places!
We're here -> attribute lookup has not found the attribute in the usual places!
('attr: ', 'a')
not a
>>>
请注意,这种矛盾的行为并不是我阅读官方 python 文档所期望的:
object.__getattr__(self, name)
当属性查找在通常的位置没有找到该属性时调用(即它不是实例属性,也不是在 self 的类树中找到)。name 是属性名称。
AttributeError
(如果他们提到这是“属性查找”知道是否在“通常的地方”找到属性的方法,那就太好了。澄清的括号在我看来充其量是不完整的。)
@property
在实践中,这会导致跟踪由于在描述符事物中引发 AttributeError 的编程错误引起的错误的问题。
>>> class MessedAttrMesser(object):
... things = {
... 'one': 0,
... 'two': 1,
... }
...
... def __getattr__(self, attr):
... try:
... return self.things[attr]
... except KeyError as e:
... raise AttributeError(e)
...
... @property
... def get_thing_three(self):
... return self.three
...
>>>
>>> blah = MessedAttrMesser()
>>> print(blah.one)
0
>>> print(blah.two)
1
>>> print(blah.get_thing_three)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 11, in __getattr__
AttributeError: 'get_thing_three'
>>>
在这种情况下,通过检查整个班级很明显会发生什么。但是,如果您依赖堆栈跟踪中的消息AttributeError: 'get_thing_three'
,那将毫无意义,因为显然,get_thing_three
它看起来与它们一样有效。
的目的kale
是为构建模型提供一个基类。因此,基本模型代码对最终程序员来说是隐藏的,并且像这样掩盖错误的原因并不理想。
最终程序员(咳咳)可能会选择@property
在他们的模型上使用描述符,并且他们的代码应该以他们期望的方式工作和失败。
问题
如何允许AttributeError
s 通过已定义的基类传播__getattr__
?