gpt4 book ai didi

python - 实现了自己的 __getattr__;遇到意外错误

转载 作者:行者123 更新时间:2023-11-28 17:19:30 24 4
gpt4 key购买 nike

这是我的简化类(有一个错误):

$ ipython

Python 2.7.6 (default, Oct 26 2016, 20:30:19)
Type "copyright", "credits" or "license" for more information.

IPython 5.1.0 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.


In [1]: import numpy as np

In [2]: class Foo(object):
...: def __init__(self):
...: self.one = 1
...: self.dct = dict(a='aaa', b='bbb')
...:
...: @property
...: def two(self):
...: # import ipdb; ipdb.set_trace()
...: np.ann # This was the spelling error I had
...: return 2
...:
...: def __getattr__(self, key):
...: """
...: Provide convenient access to values that are
...: somewhat inconvient to access, eg
...:
...: >>> foo = Foo()
...: >>> foo.dct['a'] # this obviously works
...: 'aaa'
...: >>> foo.a # but this is easier
...: 'aaa'
...:
...: In reality I have something a bit more complicated than
...: a simple dictionary (`self.dct = dict(...)`)
...:
...: """
...: print('__getattr__ with "{}"'.format(key))
...: try:
...: return self.dct[key]
...: except KeyError:
...: raise AttributeError("Can't find '{}'".format(key))
...:

使用它...

In [3]: foo = Foo()

In [4]: foo.one
Out[4]: 1

In [5]: foo.dct['a']
Out[5]: 'aaa'

In [6]: foo.a
__getattr__ with "a"
Out[6]: 'aaa'

In [7]: foo.two
__getattr__ with "two"
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-9-29e77587894c> in <module>()
----> 1 foo.two

<ipython-input-4-955e08b9c001> in __getattr__(self, key)
12 return self.dct[key]
13 except KeyError:
---> 14 raise AttributeError("Can't find '{}'".format(key))
15

AttributeError: Can't find 'two'

为什么拼写错误 np.ann 调用 foo.__getattr__ 并在我自己的 raise AttributeError 中结束 key = = '二'??

我已经逐步完成了代码(通过取消注释 set_trace() 行),但并没有真正理解它。如果有帮助,这里是输出。

In [15]: foo.two
> <ipython-input-13-915f93b88a22>(8)two()
7 import ipdb; ipdb.set_trace()
----> 8 np.ann
9 return 2

ipdb> n
AttributeError: "'module' object has no attribute 'ann'"
> <ipython-input-13-915f93b88a22>(8)two()
7 import ipdb; ipdb.set_trace()
----> 8 np.ann
9 return 2

ipdb> n
--Return--
None
> <ipython-input-13-915f93b88a22>(8)two()
7 import ipdb; ipdb.set_trace()
----> 8 np.ann
9 return 2

ipdb> n
--Call--
> <ipython-input-13-915f93b88a22>(10)__getattr__()
9 return 2
---> 10 def __getattr__(self, key):
11 print('__getattr__ with "{}"'.format(key))

ipdb> n
> <ipython-input-13-915f93b88a22>(11)__getattr__()
10 def __getattr__(self, key):
---> 11 print('__getattr__ with "{}"'.format(key))
12 try:

ipdb> n
__getattr__ with "two"
> <ipython-input-13-915f93b88a22>(12)__getattr__()
11 print('__getattr__ with "{}"'.format(key))
---> 12 try:
13 return self.dct[key]

ipdb> n
> <ipython-input-13-915f93b88a22>(13)__getattr__()
12 try:
---> 13 return self.dct[key]
14 except KeyError:

ipdb> n
KeyError: ('two',)
> <ipython-input-13-915f93b88a22>(13)__getattr__()
12 try:
---> 13 return self.dct[key]
14 except KeyError:

ipdb> n
> <ipython-input-13-915f93b88a22>(14)__getattr__()
13 return self.dct[key]
---> 14 except KeyError:
15 raise AttributeError("Can't find '{}'".format(key))

ipdb> n
> <ipython-input-13-915f93b88a22>(15)__getattr__()
14 except KeyError:
---> 15 raise AttributeError("Can't find '{}'".format(key))
16

ipdb> n
AttributeError: Attribut... 'two'",)
> <ipython-input-13-915f93b88a22>(15)__getattr__()
14 except KeyError:
---> 15 raise AttributeError("Can't find '{}'".format(key))
16

ipdb> n
--Return--
None
> <ipython-input-13-915f93b88a22>(15)__getattr__()
14 except KeyError:
---> 15 raise AttributeError("Can't find '{}'".format(key))
16

ipdb> n
AttributeError: Attribut... 'two'",)
> <ipython-input-15-29e77587894c>(1)<module>()
----> 1 foo.two

ipdb> n
--Return--
None
> <ipython-input-15-29e77587894c>(1)<module>()
----> 1 foo.two

ipdb> n
AttributeError: Attribut... 'two'",)
> /home/venv/local/lib/python2.7/site-packages/IPython/core/interactiveshell.py(2881)run_code()
2880 #rprint('Running code', repr(code_obj)) # dbg
-> 2881 exec(code_obj, self.user_global_ns, self.user_ns)
2882 finally:

如果我注释掉 @property 行,那么这个 bug 就会按预期运行,这让我相信这与装饰器有关...:

In [19]: foo.two
Out[19]: <bound method Foo.two of <__main__.Foo object at 0x7fc248156450>>

In [20]: foo.two()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-20-25d037a9762c> in <module>()
----> 1 foo.two()

<ipython-input-16-9999eb93c349> in two(self)
6 def two(self):
7 # import ipdb; ipdb.set_trace()
----> 8 np.ann
9 return 2
10 def __getattr__(self, key):

AttributeError: 'module' object has no attribute 'ann'

最佳答案

  • (正常行为)每当正常属性查找引发 AttributeError 时调用 __getattr__

  • property 更改属性查找,以便在您访问属性时执行函数。

在您的情况下,您想要访问 two 属性,该属性又会调用方法 Foo.two,该方法在以下情况下引发 AttributeError它尝试查找 np.ann。此 AttributeError 被捕获,您的 __getattr__ 被调用 key='two'。但是因为 'two' 不在你的字典中,你会得到你在那里提出的 AttributeError

关于python - 实现了自己的 __getattr__;遇到意外错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42286539/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com