Как проверить, существует ли член класса без исключения

Для примитивных типов я могу использовать проверку if in: boolean. Но если я использую синтаксис in для проверки существования члена класса, я получаю исключение NameError. Есть ли способ в Python, чтобы проверить без исключения? Или это единственный способ окружить в try, кроме блока?

Вот мой пример кода.

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"

4 ответа

Решение

Вы получаете ошибку, потому что вы используете counter (имя) а не 'counter' (строка). Тем не менее, даже если вы должны были использовать 'counter' это не будет делать то, что вы ожидаете, вы получите TypeError: argument of type 'a' is not iterable - то есть вы не можете перебирать свой пользовательский объект.

Вместо этого используйте __dict__ атрибут экземпляра:

>>> class A(object):
...     i = 0
...     def __init__(self, num):
...         self.i = num
...
>>> x = A(3)
>>> x.i
3
>>> 'i' in x.__dict__
True
>>> 'counter' in x.__dict__
False

Или более подходящим hasattr как указал Джон.

>>> hasattr(x, 'counter')
False
>>> hasattr(x, 'i')
True

Вы можете использовать hasattr

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

Вы можете сделать __contains__ функция в вашем классе, которая сообщает, какие атрибуты в классе, используя in оператор.

class myclass:

    def __init__(self, num):
        self.i = num

    def __contains__(self, attribute_name):
        return hasattr(self, attribute_name)

Тогда (почти) так же, как ваш код будет работать хорошо.

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"

Обратите внимание, что вам нужно передать строку имени атрибута, а не сам атрибут.

Правильный ответ на ваш вопрос немного зависит от того, что вы подразумеваете под членом, существующим в объекте. Если вы имеете в виду, существует ли переменная экземпляра для данного объекта, используйте hasattr как объяснили другие ответы.

Однако, если вы создаете свой собственный тип коллекции и хотите проверить определенное значение в его содержимом, тогда вы захотите дать своему классу __contains__ метод. Этот магический метод вызывается для реализации in оператор. Вот тривиальный пример, где я просто заключаю список в свой собственный объект.

class MyListWrapper(object):
    def __init__(self, iterable=[]):
        self.list = list(iterable)

    def __contains__(self, value):
        return value in self.list

Тестовая сессия:

>>> m = MyListWrapper(["foo", "bar"])
>>> "foo" in m
True
Другие вопросы по тегам