Angus Comber
Angus Comber

Reputation: 9708

How to check if a class member exists without getting exception

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

Answers (4)

Jon Clements
Jon Clements

Reputation: 142116

You can use hasattr

if hasattr(x, 'counter'):
    # whatever

Upvotes: 27

Burhan Khalid
Burhan Khalid

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

Blckknght
Blckknght

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

ijmarshall
ijmarshall

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

Related Questions