Reputation: 9708
For primitive types I can use the if in : boolean check. But if I use the in syntax to check for the existence of a class member I get a NameError exception. Is there a way in Python to check without an exception? Or is the only way to surround in try except block?
Here is my sample code.
class myclass:
i = 0
def __init__(self, num):
self.i = num
mylist = [1,2,3]
if 7 in mylist:
print "found it"
else:
print "7 not present" #prints 7 not present
x = myclass(3)
print x.i #prints 3
#below line NameError: name 'counter' is not defined
if counter in x:
print "counter in x"
else:
print "No counter in x"
Upvotes: 14
Views: 19766
Reputation: 174624
The error you get is because you are using counter
(a name) and not 'counter'
(the string). However, even if you were to use 'counter'
it would not do what you expect, you will get TypeError: argument of type 'a' is not iterable
- that is you cannot iterate over your custom object.
Instead, use hasattr
(thanks to Jon for the suggestion).
>>> x = A(3)
>>> x.i
3
>>> hasattr(x, 'counter')
False
>>> hasattr(x, 'i')
True
Upvotes: 12
Reputation: 104702
The correct answer to your question depends a bit on what you mean by a member existing in an object. If you mean, does an instance variable exist on a given object, use hasattr
as other answers have explained.
However, if you're creating your own collection type and want to check for a specific value in its contents, then you'll want to give your class a __contains__
method. That magic method is called to implement the in
operator. Here's a trivial example, where I simply wrap up a list in my own object.
class MyListWrapper(object):
def __init__(self, iterable=[]):
self.list = list(iterable)
def __contains__(self, value):
return value in self.list
Test session:
>>> m = MyListWrapper(["foo", "bar"])
>>> "foo" in m
True
Upvotes: 0
Reputation: 3487
You can make a __contains__
function in your class, which reports back what attributes are in the class using the in
operator.
class myclass:
def __init__(self, num):
self.i = num
def __contains__(self, attribute_name):
return hasattr(self, attribute_name)
Then (almost) the same as your code would work well.
x = myclass(3)
print x.i #prints 3
# prints 'No counter in x'
if 'counter' in x:
print "counter in x"
else:
print "No counter in x"
Note that you need to pass the string of the attribute name, rather than the attribute itself.
Upvotes: 2