【问题标题】:Asymmetric behavior for __getattr__, newstyle vs oldstyle classes__getattr__ 的不对称行为,新式与旧式类
【发布时间】:2010-08-05 14:39:15
【问题描述】:

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

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

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

【问题讨论】:

  • 请不要使用旧样式的类。出于明显的原因,它们已被弃用——比如这个。由于它们已被弃用,因此了解它们过去的工作方式并没有帮助。请丢弃它们并继续前进。
  • 比较新旧类的行为有助于说明新式类的工作原理,尤其是在您熟悉旧式类的情况下。他们以不同的方式工作确实不足为奇,知道新课程按预期工作令人欣慰。尽管如此,尝试理解为什么代码的解释方式与版本无关是有价值的。

标签: python coding-style new-operator getattr


【解决方案1】:

Special method lookup for new-style classes

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

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-03-13
        • 2012-05-16
        • 2011-05-09
        • 1970-01-01
        • 2012-11-28
        • 1970-01-01
        • 1970-01-01
        • 2016-04-22
        相关资源
        最近更新 更多