How do I check if an object has some attribute? For example:
>>> a = SomeClass()
>>> a.property
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: SomeClass instance has no attribute 'property'
How do I tell if a has the attribute property before using it?
Try hasattr():
if hasattr(a, 'property'):
a.property
See zweiterlinde's answer below, who offers good advice about asking forgiveness! A very pythonic approach!
The general practice in python is that, if the property is likely to be there most of the time, simply call it and either let the exception propagate, or trap it with a try/except block. This will likely be faster than hasattr. If the property is likely to not be there most of the time, or you're not sure, using hasattr will probably be faster than repeatedly falling into an exception block.
As Jarret Hardie answered, hasattr will do the trick. I would like to add, though, that many in the Python community recommend a strategy of "easier to ask for forgiveness than permission" (EAFP) rather than "look before you leap" (LBYL). See these references:
EAFP vs LBYL (was Re: A little disappointed so far)
EAFP vs. LBYL #Code Like a Pythonista: Idiomatic Python
ie:
try:
doStuff(a.property)
except AttributeError:
otherStuff()
... is preferred to:
if hasattr(a, 'property'):
doStuff(a.property)
else:
otherStuff()
You can use hasattr() or catch AttributeError, but if you really just want the value of the attribute with a default if it isn't there, the best option is just to use getattr():
getattr(a, 'property', 'default value')
I think what you are looking for is hasattr. However, I'd recommend something like this if you want to detect python properties-
try:
getattr(someObject, 'someProperty')
except AttributeError:
print "Doesn't exist"
else
print "Exists"
The disadvantage here is that attribute errors in the properties __get__ code are also caught.
Otherwise, do-
if hasattr(someObject, 'someProp'):
#Access someProp/ set someProp
pass
Docs:http://docs.python.org/library/functions.html
Warning:
The reason for my recommendation is that hasattr doesn't detect properties.
Link:http://mail.python.org/pipermail/python-dev/2005-December/058498.html
According to pydoc, hasattr(obj, prop) simply calls getattr(obj, prop) and catches exceptions. So, it is just as valid to wrap the attribute access with a try statement and catch AttributeError as it is to use hasattr() beforehand.
a = SomeClass()
try:
return a.fake_prop
except AttributeError:
return default_value
I would like to suggest avoid this:
try:
doStuff(a.property)
except AttributeError:
otherStuff()
The user #jpalecek mentioned it: If an AttributeError occurs inside doStuff(), you are lost.
Maybe this approach is better:
try:
val = a.property
except AttributeError:
otherStuff()
else:
doStuff(val)
For objects other than dictonary:
if hasattr(a, 'property'):
a.property
For dictionary, hasattr() will not work.
Many people are telling to use has_key() for dictionary, but it is depreciated.
So for dictionary, you have to use has_attr()
if a.has_attr('property'):
a['property']
Or you can also use
if 'property' in a:
hasattr() is the right answer. What I want to add is that hasattr() can be used well in conjunction with assert (to avoid unnecessary if statements and make the code more readable):
assert hasattr(a, 'property'), 'object lacks property'
print(a.property)
In case that the property is missing, the program will exit with an AssertionError and printing out the provided error message (object lacks property in this case).
As stated in another answer on SO:
Asserts should be used to test conditions that should never happen.
The purpose is to crash early in the case of a corrupt program state.
Often this is the case when a property is missing and then assert is very appropriate.
EDIT:This approach has serious limitation. It should work if the object is an iterable one. Please check the comments below.
If you are using Python 3.6 or higher like me there is a convenient alternative to check whether an object has a particular attribute:
if 'attr1' in obj1:
print("attr1 = {}".format(obj1["attr1"]))
However, I'm not sure which is the best approach right now. using hasattr(), using getattr() or using in. Comments are welcome.
Hope you expecting hasattr(), but try to avoid hasattr() and please prefer getattr(). getattr() is faster than hasattr()
using hasattr():
if hasattr(a, 'property'):
print a.property
same here i am using getattr to get property if there is no property it return none
property = getattr(a,"property",None)
if property:
print property
Depending on the situation you can check with isinstance what kind of object you have, and then use the corresponding attributes. With the introduction of abstract base classes in Python 2.6/3.0 this approach has also become much more powerful (basically ABCs allow for a more sophisticated way of duck typing).
One situation were this is useful would be if two different objects have an attribute with the same name, but with different meaning. Using only hasattr might then lead to strange errors.
One nice example is the distinction between iterators and iterables (see this question). The __iter__ methods in an iterator and an iterable have the same name but are semantically quite different! So hasattr is useless, but isinstance together with ABC's provides a clean solution.
However, I agree that in most situations the hasattr approach (described in other answers) is the most appropriate solution.
Here's a very intuitive approach :
if 'property' in dir(a):
a.property
If a is a dictionary, you can check normally
if 'property' in a:
a.property
This is super simple, just use dir(object)
This will return a list of every available function and attribute of the object.
You can check whether object contains attribute by using hasattr builtin method.
For an instance if your object is a and you want to check for attribute stuff
>>> class a:
... stuff = "something"
...
>>> hasattr(a,'stuff')
True
>>> hasattr(a,'other_stuff')
False
The method signature itself is hasattr(object, name) -> bool which mean if object has attribute which is passed to second argument in hasattr than it gives boolean True or False according to the presence of name attribute in object.
You can use hasattr() to check if object or class has an attribute in Python.
For example, there is Person class as shown below:
class Person:
greeting = "Hello"
def __init__(self, name, age):
self.name = name
self.age = age
def test(self):
print("Test")
Then, you can use hasattr() for object as shown below:
obj = Person("John", 27)
obj.gender = "Male"
print("greeting:", hasattr(obj, 'greeting'))
print("name:", hasattr(obj, 'name'))
print("age:", hasattr(obj, 'age'))
print("gender:", hasattr(obj, 'gender'))
print("test:", hasattr(obj, 'test'))
print("__init__:", hasattr(obj, '__init__'))
print("__str__:", hasattr(obj, '__str__'))
print("__module__:", hasattr(obj, '__module__'))
Output:
greeting: True
name: True
age: True
gender: True
test: True
__init__: True
__str__: True
__module__: True
And, you can also use hasattr() directly for class name as shown below:
print("greeting:", hasattr(Person, 'greeting'))
print("name:", hasattr(Person, 'name'))
print("age:", hasattr(Person, 'age'))
print("gender:", hasattr(Person, 'gender'))
print("test:", hasattr(Person, 'test'))
print("__init__:", hasattr(Person, '__init__'))
print("__str__:", hasattr(Person, '__str__'))
print("__module__:", hasattr(Person, '__module__'))
Output:
greeting: True
name: False
age: False
gender: False
test: True
__init__: True
__str__: True
__module__: True
Another possible option, but it depends if what you mean by before:
undefined = object()
class Widget:
def __init__(self):
self.bar = 1
def zoom(self):
print("zoom!")
a = Widget()
bar = getattr(a, "bar", undefined)
if bar is not undefined:
print("bar:%s" % (bar))
foo = getattr(a, "foo", undefined)
if foo is not undefined:
print("foo:%s" % (foo))
zoom = getattr(a, "zoom", undefined)
if zoom is not undefined:
zoom()
output:
bar:1
zoom!
This allows you to even check for None-valued attributes.
But! Be very careful you don't accidentally instantiate and compare undefined multiple places because the is will never work in that case.
Update:
because of what I was warning about in the above paragraph, having multiple undefineds that never match, I have recently slightly modified this pattern:
undefined = NotImplemented
NotImplemented, not to be confused with NotImplementedError, is a built-in: it semi-matches the intent of a JS undefined and you can reuse its definition everywhere and it will always match. The drawbacks is that it is "truthy" in booleans and it can look weird in logs and stack traces (but you quickly get over it when you know it only appears in this context).
Related
I have a question related to Python unittest.mock.Mock and spec_set functionalities.
My goal is to create a Mock with the following functionalities:
It has a spec of an arbitrary class I decide at creation time.
I must be able to assign on the mock only attributes or methods according to the spec of point 1
The Mock must raise AttributeError in the following situations:
I try to assign an attribute that is not in the spec
I call or retrieve a property that is either missing in the spec_set, or present in the spec_set but assigned according to the above point.
Some examples of the behavior I would like:
class MyClass:
property: int = 5
def func() -> int:
pass
# MySpecialMock is the Mock with the functionalities I am dreaming about :D
mock = MyMySpecialMock(spec_set=MyClass)
mock.not_existing # Raise AttributeError
mock.func() # Raise AttributeError
mock.func = lambda: "it works"
mock.func() # Returns "it works"
I have tried multiple solutions without any luck, or without being explicitly verbose. The following are some examples:
Using Mock(spec_set=...), but it does not raise errors in case I call a specced attribute which I did not explicitly set
Using Mock(spec_set=...) and explicitly override every attribute with a function with an Exception side effect, but it is quite verbose since I must repeat all the attributes...
My goal is to find a way to automatize 2, but I have no clean way to do so. Did you ever encounter such a problem, and solve it?
For the curious ones, the goal is being able to enhance the separation of unit testings; I want to be sure that my mocks are called only on the methods I explicitly set, to avoid weird and unexpected side effects.
Thank you in advance!
spec_set defines a mock object which is the same as the class, but then doesn't allow any changes to be made to it, since it defines special __getattr__ and __setattr__. This means that the first test (calling a non-existent attr) will fail as expected, but then so will trying to set an attr:
from unitest import mock
class X:
pass
m = mock.Mock(spec_set=X)
m.func()
# __getattr__: AttributeError: Mock object has no attribute 'func'
m.func = lambda: "it works"
# __setattr__: AttributeError: Mock object has no attribute 'func'
Instead, you can use create_autospec() which copies an existing function, and adds the mock functions to it, but without affecting __setattr__:
n = mock.create_autospec(X)
n.func()
# __getattr__: AttributeError: Mock object has no attribute 'func'
n.func = lambda: "it works"
n.func()
# 'it works'
I think I found a satisfying answer to my problem, by using the dir method.
To create the Mock with the requirements I listed above, it should be enough to do the following:
def create_mock(spec: Any) -> Mock:
mock = Mock(spec_set=spec)
attributes_to_override = dir(spec)
for attr in filter(lambda name: not name.startswith("__"), attributes_to_override):
setattr(mock, attr, Mock(side_effect=AttributeError(f"{attr} not implemented")))
return mock
The documentation lists many magic methods. But I don't think it is enough. It does not tell me what methods are called when I do for x in c.
To do this, I tried a simple code snippet to print each attribute reference:
class Print(object):
def __getattribute__(self, item):
print(item)
return super().__getattribute__(item)
a = Print()
Sometimes it works:
import pickle
pickle.dumps(a)
# print the following and then raise an error
__reduce_ex__
__reduce__
__getstate__
__class__
Then I know pickle.dump calls these magic methods.
But sometimes it does not work:
for x in a:
continue
# direct error, no print
Are there any way to tell what magic methods are called in a python statement?
Update:
It seems Cpython bypasses getattribute calls for some special methods for speedup. Check special-method-lookup section for details.
Therefore, the answer seems to be no. We cannot catch each attribute reference.
Just take this example:
class C:
pass
c = C()
c.__len__ = lambda: 5
len(c)
# TypeError: object of type 'C' has no len()
I have to check if foo is a attribute of myclass.
Right now I do
def myclass():
try:
self.foo
except AttributeError:
self.foo = 'default'
while I think I should be doing
if not hasattr(self,'foo'):
self.foo = 'default'
Is there any difference between the two approaches, and which one should be preferred?
I am looking for the following criteria:
Consistency with multiple inheritance
Portability across python versions
Limited overhead
Both of those approaches are functionally equivalent.
From the hasattr docs:
hasattr(object, name)
The arguments are an object and a string. The result is True if the string is the name of one of the object’s attributes, False if
not. (This is implemented by calling getattr(object, name) and seeing
whether it raises an AttributeError or not.)
And the getattr docs state the following:
getattr(x, 'foobar') is equivalent to x.foobar
Regarding speed, my tests show that hasattr is a little faster. The results with 1 million iterations were:
hasattr: 0.6325701880014094 seconds
try: 0.8206841319988598 seconds
Unless you're writing highly optimized code, there's no need to worry about such a small difference. There's also no need to worry about compatibility with python versions; attribute access and hasattr are available in every version of python.
In the end, it comes down to preference. Choose whichever you find more readable.
Why does hasattr say that the instance doesn't have a foo attribute?
>>> class A(object):
... #property
... def foo(self):
... ErrorErrorError
...
>>> a = A()
>>> hasattr(a, 'foo')
False
I expected:
>>> hasattr(a, 'foo')
NameError: name 'ErrorErrorError' is not defined`
The Python 2 implementation of hasattr is fairly naive, it just tries to access that attribute and see whether it raises an exception or not.
Unfortunately, hasattr will eat any exception type, not just an AttributeError matching the name of the attribute which was attempted to access. It caught a NameError in the example shown, which causes the incorrect result of False to be returned there. To add insult to injury, any unhandled exceptions inside properties will get swallowed, and errors inside property code can get lost, masking bugs.
In Python 3.2+, the behavior has been corrected:
hasattr(object, name)
The arguments are an object and a string. The result is True if the string is the name of one of the object’s attributes, False if not. (This is implemented by calling getattr(object, name) and seeing whether it raises an AttributeError or not.)
The fix is here, but that change didn't get backported.
If the Python 2 behavior causes trouble for you, consider to avoid using hasattr; instead you can use a try/except around getattr, catching only the AttributeError exception type and letting any other exceptions raise unhandled.
Is it possible to make a decorator that makes attributes lazy that do not eval when you try to access it with hasattr()? I worked out how to make it lazy, but hasattr() makes it evaluate prematurely. E.g.,
class lazyattribute:
# Magic.
class A:
#lazyattribute
def bar(self):
print("Computing")
return 5
>>> a = A()
>>> print(a.bar)
'Computing'
5
>>> print(a.bar)
5
>>> b = A()
>>> hasattr(b, 'bar')
'Computing'
5
# Wanted output: 5
It may be difficult to do. From the hasattr documentation:
hasattr(object, name)
The arguments are an object and a string. The result is True if the string is the name of one of the object’s attributes, False if not. (This is implemented by calling getattr(object, name) and seeing whether it raises an exception or not.)
Since attributes may be generated dynamically by a __getattr__ method, there's no other way to reliably check for their presence. For your special situation, maybe testing the dictionaries explicitly would be enough:
any('bar' in d for d in (b.__dict__, b.__class__.__dict__))
What nobody seems to have addressed so far is that perhaps the best thing to do is not to use hasattr(). Instead, go for EAFP (Easier to Ask Forgiveness than Permission).
try:
x = foo.bar
except AttributeError:
# what went in your else-block
...
else:
# what went in your if hasattr(foo, "bar") block
...
This is obviously not a drop-in replacement, and you might have to move stuff around a bit, but it's possibly the "nicest" solution (subjectively, of course).
The problem is that hasattr uses getattr so your attribute is always going to be evaluated when you use hasattr. If you post the code for your lazyattribute magic hopefully someone can suggest an alternative way of testing the presence of the attribute which doesn't require hasattr or getattr. See the help for hasattr:
>>> help(hasattr)
Help on built-in function hasattr in module __builtin__:
hasattr(...)
hasattr(object, name) -> bool
Return whether the object has an attribute with the given name.
(This is done by calling getattr(object, name) and catching exceptions.)
I'm curious why you need something like this. If hasattr ends up calling your "compute function", then so be it. Just how lazy does your property need to be anyway?
Still, here's a rather inelegeant way of doing it by examining the calling function's name. It could probably be coded a little better, but I don't think it should ever be used seriously.
import inspect
class lazyattribute(object):
def __init__(self, func):
self.func = func
def __get__(self, obj, kls=None):
if obj is None or inspect.stack()[1][4][0].startswith('hasattr'):
return None
value = self.func(obj)
setattr(obj, self.func.__name__, value)
return value
class Foo(object):
#lazyattribute
def bar(self):
return 42
orip's answer will be enough only if your object's inheritance has one level of depth.
You should iterate over the method resolution order of object's class to have a complete solution:
from itertools import chain
def lazy_hasattr(obj, name):
# checks for the attribute without triggering __get__
return any(name in d for d in chain((obj.__dict__,),
(c.__dict__ for c in obj.__class__.mro())))
# Usage:
lazy_hasattr(b,'bar')
well the fix is a little hackish but it consists of the following
rename hasattr (say as _hasattr)
rebind hasattr as the following:
def hasattr(obj, name):
try:
return obj._hasattr(name) or _hasattr(obj, name)
except:
return _hasattr(obj, name)
implement class method _hasattr by checking some data structure (ie. array) which is populated with all the lazy attribute names (for an array you'd say: name in lazyAttrArray)
finally somehow have your #lazyattribute decorator add items into some sort of structure (like the array we mentioned above), and then when you call _hasattr then you look in that structure
this is the step that I'm not quite sure how you'd implement 'cause I haven't worked with creating my own decorators