Python 如何区分hasattr和uu getattr_uuu中的普通属性访问?
请查看Python 如何区分hasattr和uu getattr_uuu中的普通属性访问?,python,Python,请查看\uu getattr\uuu中的注释。我该怎么做?我正在使用Python3。原因是我想动态创建属性,但我不想在使用hasattr时这样做。谢谢。你不能不作弊。正如上面所说: 这[即,hasattr]是通过调用getattr(object,name)并查看它是否引发异常来实现的 换句话说,如果不阻止getattr,就无法阻止hasattr,这基本上意味着如果您关心访问属性,就根本无法阻止hasattr 我所说的“作弊”是指聪明人喜欢在这里发布的解决方案之一,它涉及到基本上所有Python的
\uu getattr\uuu
中的注释。我该怎么做?我正在使用Python3。原因是我想动态创建属性,但我不想在使用hasattr时这样做。谢谢。你不能不作弊。正如上面所说:
这[即,hasattr
]是通过调用getattr(object,name)
并查看它是否引发异常来实现的
换句话说,如果不阻止getattr
,就无法阻止hasattr
,这基本上意味着如果您关心访问属性,就根本无法阻止hasattr
我所说的“作弊”是指聪明人喜欢在这里发布的解决方案之一,它涉及到基本上所有Python的最终运行。它们通常涉及重新分配内置项、检查/操作调用堆栈、使用内省查看文字源代码、修改对象的“机密”内部属性等。例如,您可以查看调用堆栈以查看hasattr
是否在调用链中。这种类型的解决方案是可能的,但非常脆弱,有可能在未来的Python版本中、在非CPython实现中或在使用另一种同样丑陋和狡猾的黑客的情况下被破坏
您可以看到类似的问题和一些讨论。此讨论适用于Python 3。(事实证明它也适用于Python 2.7) 不完全是您描述的方式,但以下几点可能会有所帮助:
只有在正常方式下找不到属性时才会被访问\uuuu getattr\uuuu
检查是否引发了AttributeErrorhasattr()
class a_class:
def __getattr__(self, name):
# if called by hasattr(a, 'b') not by a.b
# print("I am called by hasattr")
print(name)
a = a_class()
a.b_attr
hasattr(a, 'c_attr')
您的代码抛出一个错误。调用
print('c={}.format(a.c))
后,它抛出AttributeError:'a'对象没有属性“c”
。顺便说一下,如果属性是通过点符号a.c访问的,或者通过调用hasattr(a,'c')检查的,那么代码不会记录。所以它没有回答这个问题。代码正在运行,只是用Python2.7和Python3.6进行了测试。我在repl.it上用两个Python版本测试了您的代码:和。它们都抛出相同的AttributeError
。从未使用过。在本机pythonshell(idle)和jupyter上运行代码,请在它们上尝试。代码是合法的,看起来像是你使用的网站上的一个bug。
>>> class A:
... def __init__(self, a=1, b=2):
... self.a = a
... self.b = b
...
... def __getattr__(self, name):
... print('calling __getattr__')
... print('This is instance attributes: {}'.format(self.__dict__))
...
... if name not in ('c', 'd'):
... raise AttributeError()
... else:
... return 'My Value'
... return 'Default'
>>>
>>> a = A()
>>> print('a = {}'.format(a.a))
a = 1
>>> print('c = {}'.format(a.c))
calling __getattr__
This is instance attributes: {'a': 1, 'b': 2}
c = My Value
>>> print('hasattr(a, "e") returns {}'.format(hasattr(a, 'e')))
calling __getattr__
This is instance attributes: {'a': 1, 'b': 2}
hasattr(a, "e") returns False
>>>