python中非常奇怪的getattr行为

python中非常奇怪的getattr行为,python,python-2.7,Python,Python 2.7,我的代码中有一个错误(类似于下面的错误),但结果对我来说很奇怪。有人能给我解释一下,getattr是如何被打成“你好”的吗 其输出为: bang hello Traceback (most recent call last): File "test.py", line 17, in <module> print c.b.bang File "test.py", line 5, in __getattr__ return self.hello File "t

我的代码中有一个错误(类似于下面的错误),但结果对我来说很奇怪。有人能给我解释一下,getattr是如何被打成“你好”的吗

其输出为:

bang
hello
Traceback (most recent call last):
  File "test.py", line 17, in <module>
    print c.b.bang
  File "test.py", line 5, in __getattr__
    return self.hello
  File "test.py", line 4, in __getattr__
    assert name != 'hello'
AssertionError

shell returned 1
bang
你好
回溯(最近一次呼叫最后一次):
文件“test.py”,第17行,在
打印c.b.bang
文件“test.py”,第5行,在__
你好
文件“test.py”,第4行,在__
断言名称!='你好’
断言错误
壳返回1

我当然知道C中没有durp属性(这就是我所说的错误)。但是,我不希望以hello作为字符串调用
\uuuu getattr\uuuu
。我觉得我对
\uuuuu getattr\uuuuu
的工作方式没有什么基本的了解。

\uuuu getattr\uuuuu
在通过“常用方法”访问属性失败时被调用。Python知道“常用方法”是否失败的方式是引发AttributeError。但是,它无法判断此AttributeError是在尝试获取您试图获取的原始属性时引发的,还是在该过程中访问的其他属性。下面是发生的情况:

  • Python试图访问
    c.b.bang
  • b对象没有属性“bang”,因此调用
    \uu getattr\uuu
  • \uuu getattr\uuu
    尝试获取
    self.hello
  • Python查找属性
    hello
    ,该属性的值是一个属性
  • 在尝试计算
    self.hello
    时,Python运行
    hello
    属性
  • 运行
    hello
    属性尝试访问不存在的属性
    durp
    。这会引发AttributeError
  • 由于AttributeError是在尝试计算
    self.hello
    时提出的,Python认为“通常的方法”中没有这样的属性可用。因此,它以“hello”作为参数调用
    \uuuu getattr\uuuu

  • 这种行为令人困惑,但基本上是Python中属性查找工作方式不可避免的副作用。知道“普通属性查找不起作用”的唯一方法是引发AttributeError。关于这一点,显然人们还在努力,但到目前为止还没有真正的解决方案。

    return self.hello
    a.的定义中

    class A(object):
        def __getattr__(self, name):
            print name
            assert name != 'hello'
            return self.hello
    

    触发一个新的属性搜索,这次使用
    'hello'
    作为
    name
    参数的值,这会导致您的断言失败

    ,因此基本上C类会创建一个AttributeError异常,因为C中没有getattr,它只会遇到“stale”,而a会尝试处理它,因为存在异常,即使它不是起源于A类,跛子。这似乎是一种奇怪的方式来确定“通常的方法”失败了,但这肯定能解释发生了什么。你能在你的评论中添加以下代码吗:以简化的形式?我希望有一个单一的参考位置来解释这个问题(你的评论),并显示最小的代码示例来重现这个问题(链接)。@WloHu:我认为这不是处理这个问题的好方法。如果你想找一个地方,你可以用你想要的信息创建你自己的网页。我发布的是对所问问题的回答,我不认为仅仅因为你发现了一些你想与这个答案结合在一起的其他博客文章,就用不同的例子来混乱答案是一个好主意。如果我在hello属性中没有错误,那么断言将永远不会失败,因为getattr永远不会被“hello”字符串调用。从概念上讲,它不应该被调用,因为hello属性存在,但正如BrenBarn解释的那样,python在处理“通常方法失败”方法方面有点奇怪,因此类a尝试处理类C的不存在属性。感谢注释中的更正,BrenBarn是正确的
    class A(object):
        def __getattr__(self, name):
            print name
            assert name != 'hello'
            return self.hello