8

这是我第一次在这里写,如果信息没有重点或太长,请见谅。

我有兴趣了解更多关于如何在需要时获取对象的属性。所以我在这里阅读了标题为“数据模型”的 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__为什么在使用像 + 这样的内置运算符时,旧式类和新式类之间会出现这种不对称行为?有人可以帮助我了解发生了什么,以及我在阅读文档时的错误是什么?

非常感谢,非常感谢您的帮助!

4

3 回答 3

5

请参阅新式类的特殊方法查找

特殊方法直接在类对象、实例对象中查找,因此__getattr__()__getattribute__()绕过。出于完全相同的原因,instance.__add__ = foobar不起作用。

这样做是为了加快属性访问。特殊方法被非常频繁地调用,并且使它们受制于标准,相当复杂的属性查找会显着减慢解释器的速度。

旧式类的属性查找要简单得多(最值得注意的是旧式类不支持描述符),因此没有理由在旧式类中区别对待特殊方法。

于 2010-08-05T15:00:21.223 回答
1

您的__getattr__函数没有返回任何内容。我不知道为什么旧式类__getattr__在寻找之前做的是__add__,但它是,这是试图调用返回值是None.

新式类做得对:你没有定义__add__,所以它不知道如何添加它们。

于 2010-08-05T14:47:18.777 回答
0

来自 Python 文档的更多信息:

http://docs.python.org/reference/datamodel.html#customizing-attribute-access

于 2010-08-05T14:49:29.707 回答