这是我第一次写这篇文章,对不起,如果邮件没有被删除或太长。
我有兴趣了解更多关于如何在需要时获取对象的属性。所以我阅读了标题为“数据模型”here的Python 2.7文档,我遇到了__getattr__
,为了检查我是否理解了它的行为,我编写了这些简单(和不完整)的字符串包装器。
class OldStr:
def __init__(self,val):
self.field=val
def __getattr__(self,name):
print "method __getattr__, attribute requested "+name
class NewStr(object):
def __init__(self,val):
self.field=val
def __getattr__(self,name):
print "method __getattr__, attribute requested "+name
正如你所看到的那样,除了作为旧式和新式课程之外,它们是相同的。由于引用的文本说__getattr__
是“当一个属性查找没有找到通常位置的属性时调用”,我想在这些类的两个实例上尝试+操作来查看发生了什么,期望相同的行为
但是我得到的结果让我感到困惑:
>>> x=OldStr("test")
>>> x+x
method __getattr__, attribute requested __coerce__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not callable
好!我没有为__coerce__
定义一个方法(虽然我期待__add__
的请求,但是没关系:),所以__getattr__
参与其中并返回了一个无用的东西。但是接下来
>>> y=NewStr("test")
>>> y+y
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'NewStr' and 'NewStr'
为什么在使用像+这样的内置运算符时,旧式类__getattr__
与新式类之间存在这种不对称行为?有人可以帮我理解发生了什么,以及我在阅读文档时的错误是什么?
非常感谢,非常感谢您的帮助!
答案 0 :(得分:5)
见Special method lookup for new-style classes。
在类对象中直接查找特殊方法,实例对象因此绕过__getattr__()
和__getattribute__()
。出于同样的原因,instance.__add__ = foobar
不起作用。
这样做是为了加速属性访问。特殊方法被非常频繁地调用,并且使它们受到标准的,相当复杂的属性查找的影响,这将大大减慢解释器的速度。
旧式类的属性查找要复杂得多(最值得注意的是旧式类不支持描述符),因此没有理由在旧式类中以不同方式处理特殊方法。
答案 1 :(得分:2)
您的__getattr__
函数未返回任何内容。我不知道为什么旧式类在查找__getattr__
之前正在执行__add__
,但它确实是,并且这是尝试调用返回值None
。
新式课程正确:您尚未定义__add__
,因此它不知道如何添加它们。
答案 2 :(得分:0)