Reputation: 956
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')
Please take a look the comment inside __getattr__
. How do I do that? I am using Python 3. The reason is I want to create attribute dynamically but I don't want to do that when using hasattr. Thanks.
Upvotes: 8
Views: 1423
Reputation: 2932
This discussion applies to Python 3. (turns out it works on Python 2.7 as well)
Not exactly the way you described but the following points might help:
__getattr__
will only be accessed when attribute is not found under normal wayhasattr()
check if AttributeError is raisedSee if the following code help!
>>> 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
>>>
Upvotes: 0
Reputation: 251355
You can't, without cheating. As the documentation says:
This [that is,
hasattr
] is implemented by callinggetattr(object, name)
and seeing whether it raises an exception or not.
In other words, you can't block hasattr
without also blocking getattr
, which basically means you can't block hasattr
at all if you care about accessing attributes.
By "cheating" I mean one of these solutions that clever people like to post on here that involve an end-run around essentially all of Python. They typically involve reassigning builtins, inspecting/manipulating the call stack, using introspection to peek at the literal source code, modifying "secret" internal attributes of objects, and so on. For instance, you could look at the call stack to see if hasattr
is in the call chain. This type of solution is possible, but extremely fragile, with possibility of breaking in future Python versions, on non-CPython implementations, or in situations where another equally ugly and devious hack is also being used.
You can see a similar question and some discussion here.
Upvotes: 12