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')
请查看__getattr__
内的评论。我怎么做?我正在使用Python 3.原因是我想动态创建属性但我不想在使用hasattr时这样做。感谢。
答案 0 :(得分:10)
你不能没有作弊。正如the documentation所说:
这个[
hasattr
]是通过调用getattr(object, name)
并查看是否引发异常来实现的。
换句话说,如果不阻止hasattr
,则无法阻止getattr
,这基本上意味着如果您关心访问属性,则根本无法阻止hasattr
。
通过“作弊”我的意思是这些解决方案中的一个,聪明的人喜欢在这里发布涉及基本上所有Python的最终运行。它们通常涉及重新分配内置函数,检查/操作调用堆栈,使用内省来查看文字源代码,修改对象的“秘密”内部属性等等。例如,您可以查看调用堆栈以查看调用链中是否有hasattr
。这种类型的解决方案是可能的,但是非常脆弱,可能会在未来的Python版本中破坏,在非CPython实现上,或者在使用另一个同样丑陋和狡猾的黑客的情况下。
您可以看到类似的问题和一些讨论here。
答案 1 :(得分:0)
此讨论适用于Python3。(事实证明它也适用于Python 2.7)
与您描述的方式不完全相同,但以下几点可能会有所帮助:
__getattr__
仅在以常规方式找不到属性时才能访问hasattr()
检查是否引发了AttributeError 看看下面的代码是否有帮助!
>>> 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
>>>