__getattr __,newstyle vs oldstyle类的不对称行为

Fil*_*ppo 8 python coding-style new-operator getattr

这是我第一次写这篇文章,对不起,如果邮件没有被批评或太长.

我有兴趣了解更多关于如何在需要时获取对象的属性.所以我在这里阅读了标题为"数据模型"的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
Run Code Online (Sandbox Code Playgroud)

正如你所看到的那样,除了作为旧式和新式的课程外,它们是相同的.由于引用的文本说__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
Run Code Online (Sandbox Code Playgroud)

好!我没有定义一个方法__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'
Run Code Online (Sandbox Code Playgroud)

为什么__getattr__在使用像+这样的内置运算符时,在oldstyle类和newstyle类之间存在这种不对称行为?有人可以帮我理解发生了什么,以及我在阅读文档时的错误是什么?

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

lun*_*orn 5

请参阅特殊方法查找新类

特殊的方法是直接抬头的类对象,实例对象,因此__getattr__()__getattribute__()被绕过。出于完全相同的原因,instance.__add__ = foobar它不起作用。

这样做是为了加快属性访问。特殊方法的调用非常频繁,使它们服从于标准的,相当复杂的属性查找会大大降低解释程序的速度。

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


Kat*_*iel 1

您的__getattr__函数没有返回任何内容。我不知道为什么旧式类会__getattr__在查找之前执行此__add__操作,但确实如此,并且这是试图调用返回值,即None

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