Как узнать, есть ли у объекта атрибут в Python

avatar
Lucas Gabriel Sánchez
4 марта 2009 в 14:45
1066362
16
1996

Есть ли в Python способ определить, есть ли у объекта какой-либо атрибут? Например:

>>> a = SomeClass()
>>> a.someProperty = value
>>> a.property
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: SomeClass instance has no attribute 'property'

Как узнать, имеет ли a атрибут property перед его использованием?

Источник

Ответы (16)

avatar
Jarret Hardie
4 марта 2009 в 14:48
2821

Попробуйте hasattr():

if hasattr(a, 'property'):
    a.property

РЕДАКТИРОВАТЬ: см. Ниже ответ Цвайтерлинде, который дает хороший совет о том, как просить прощения! Очень питонический подход!

Общая практика в Python заключается в том, что, если свойство, вероятно, будет присутствовать большую часть времени, просто вызовите его и либо позвольте исключению распространиться, либо перехватите его с помощью блока try / except. Вероятно, это будет быстрее, чем hasattr. Если свойство, вероятно, не будет там большую часть времени или вы не уверены, использование hasattr, вероятно, будет быстрее, чем многократное попадание в блок исключений.

riviera
8 апреля 2011 в 12:54
22

Кажется, он также работает для проверки функций в пространстве имен, например: import string hasattr(string, "lower")

Jeff Tratner
27 апреля 2012 в 03:04
18

hasattr - это то же самое, что и использование try / except AttributeError: в строке документации hasattr (в Python 2.7) говорится, что он использует getattr для перехвата исключений.

Martin Geisler
24 апреля 2013 в 07:44
9

@JeffTratner: hasattr, к сожалению, не точно то же самое, что try: ... except AttributeError: в Python 2.x, поскольку hasattr будет перехватить все исключения . См. Мой ответ для примера и простого обходного пути.

AnandShiva
4 апреля 2021 в 12:13
0

hasattr не работает, если ваш объект - dict. В этих случаях используйте оператор in или метод haskey.

avatar
Shashi
23 июня 2021 в 16:04
1

Для объектов, отличных от словаря:

if hasattr(a, 'property'):
    a.property

Для словаря hasattr () не будет работать.

Многие люди советуют использовать has_key () для словаря, но это обесценилось. Итак, для словаря вы должны использовать has_attr ()

if a.has_key('property'):
    a['property']
 
avatar
AnandShiva
4 апреля 2021 в 12:10
-1

Следует отметить, что если объект, на который вы ссылаетесь, является 'dict', то hasattr не работает.

hasattr не проверяет элементы словаря. Используйте вместо него в операторе или has_key метод

d = {'a': 1}
d.has_key('a') #True
'a' in d #True

avatar
F.M.F.
28 мая 2020 в 12:15
2

hasattr() - правильный ответ. Я хочу добавить, что hasattr() также можно хорошо использовать вместе с assert (чтобы избежать ненужных инструкций if и сделать код более читаемым):

assert hasattr(a, 'property'), 'object lacks property' 

Как указано в другом ответе на SO: утверждения следует использовать для проверки условий, которые никогда не должны происходить. Целью является ранний сбой в случае поврежденного состояния программы.

Lucas Gabriel Sánchez
28 мая 2020 в 12:19
1

Это полезно, но не всегда. Возможно, я хотел проверить, есть ли у объекта свойство, а затем добавить его в первый раз, или, может быть, мне нужно запустить другой код для объектов с этим свойством. Когда код не может продолжаться, утверждение может быть в порядке. Но опять же, это не всегда так. Важно использовать hasattr, а не окружающий код.

avatar
JL Peyret
14 августа 2019 в 00:52
0

Другой возможный вариант, но это зависит от того, имеется ли в виду под перед :

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()

вывод:

bar:1
zoom!

Это позволяет вам даже проверять атрибуты без значений.

Но! Будьте очень осторожны, чтобы случайно не создать и не сравнить undefined в нескольких местах, потому что is никогда не будет работать в этом случае.

Обновление:

из-за того, о чем я предупреждал в предыдущем абзаце, имея несколько неопределенных значений, которые никогда не совпадают, я недавно немного изменил этот шаблон:

undefined = NotImplemented

NotImplemented, не путать с NotImplementedError, является встроенным: он частично совпадает с намерением JS undefined, и вы можете повторно использовать его определение везде, и оно всегда будет совпадать. Недостатком является то, что это "правдиво" в логических значениях и может выглядеть странно в журналах и трассировках стека (но вы быстро преодолеете это, когда знаете, что оно появляется только в этом контексте).

avatar
Alec
25 мая 2019 в 04:00
10

Вот очень интуитивный подход:

if 'property' in dir(a):
    a.property
avatar
Sean Christians
13 марта 2019 в 01:42
2

Это очень просто, просто используйте dir(object )
Будет возвращен список всех доступных функций и атрибутов объекта.

avatar
Devang Padhiyar
9 марта 2019 в 15:54
1

Проверить, содержит ли object атрибут, можно с помощью встроенного метода hasattr.

Например, если ваш объект a и вы хотите проверить атрибут stuff

>>> class a:
...     stuff = "something"
... 
>>> hasattr(a,'stuff')
True
>>> hasattr(a,'other_stuff')
False

Сама сигнатура метода - hasattr(object, name) -> bool, что означает, что если object имеет атрибут , который передается второму аргументу в hasattr, чем он дает логическое значение True или <339011> в соответствии с присутствием <339011> из name атрибута в объекте.

avatar
nayak
22 июня 2017 в 06:32
15

РЕДАКТИРОВАТЬ : у этого подхода есть серьезные ограничения. Он должен работать, если объект итерируемый . Пожалуйста, проверьте комментарии ниже.

Если вы используете Python 3.6 или выше, как я, есть удобная альтернатива для проверки наличия у объекта определенного атрибута:

if 'attr1' in obj1:
    print("attr1 = {}".format(obj1["attr1"]))

Однако я не уверен, какой подход сейчас лучший. используя hasattr(), используя getattr() или используя in. Комментарии приветствуются.

Seth Difley
5 октября 2017 в 13:06
7

in ключевое слово работает для проверки повторяемых типов. Например, 'foo' in None вызывает ошибку TypeError: argument of type 'NoneType' is not iterable. Исправление состоит в том, чтобы перед использованием in проверить, является ли тип повторяемым. После исправления крайних случаев, таких как не повторяющийся тип, вам, вероятно, лучше использовать hasattr(), потому что он предназначен для обработки крайних случаев.

ShadowRanger
25 апреля 2018 в 19:37
3

Это не имеет ничего общего с доступом к атрибутам. Понятия не имею, как за него проголосовали. Единственное сходство, которое он имеет для доступа к атрибутам, заключается в том, что вы используете dict в качестве «легкого объекта», аналогично дизайну объектов JavaScript, но большинство обычных классов не будут поддерживать это в целом (получение варианта ошибки, упомянутой @SethDifley).

avatar
Janarthanan Ramu
30 декабря 2016 в 07:49
15

Надеюсь, вы ожидаете hasattr (), но постарайтесь избегать hasattr () и предпочтите getattr (). getattr () быстрее hasattr ()

с использованием hasattr ():

 if hasattr(a, 'property'):
     print a.property

здесь же я использую getattr для получения свойства, если нет свойства, которое оно не возвращает

   property = getattr(a,"property",None)
    if property:
        print property
Groosha
25 июля 2020 в 11:20
0

getattr() is faster than hasattr(), не могли бы вы это прокомментировать? Почему быстрее?

Janarthanan Ramu
27 июля 2020 в 18:14
2

@Groosha Есть много вещей, чтобы упростить hasattr () изнутри, нужно вызвать getattr () для выполнения своей операции, поэтому вместо вызова нескольких методов мы можем использовать прямой getattr (), проверьте этот docs.python.org/3 /library/functions.html#hasattr

user9538
14 июля 2021 в 00:02
0

Но если свойство действительно существует и его значение False, вы можете получить ложное срабатывание.

avatar
Maico
26 августа 2016 в 13:04
30

Я бы посоветовал этого избежать:

try:
    doStuff(a.property)
except AttributeError:
    otherStuff()

Пользователь @jpalecek упомянул об этом: Если AttributeError встречается внутри doStuff(), вы потерялись.

Может быть, этот подход лучше:

try:
    val = a.property
except AttributeError:
    otherStuff()
else:
    doStuff(val)
avatar
Carl Meyer
4 марта 2009 в 17:54
569

Вы можете использовать hasattr() или поймать AttributeError, но если вам действительно нужно значение атрибута со значением по умолчанию, если его нет, лучшим вариантом будет просто использовать getattr():

getattr(a, 'property', 'default value')
Peter M. Elias
2 января 2013 в 16:17
17

Это решает обе вышеупомянутые проблемы: a) неоднозначность источника возможной AttributeError, b) сохранение подхода EAFP.

fatuhoku
24 сентября 2013 в 11:36
7

Это также 25% строк кода. Конечно, это лучшее решение.

Carl Meyer
1 декабря 2015 в 05:48
20

Это лучшее решение, «если вам действительно нужно значение атрибута по умолчанию». Хотя я считаю, что это то, чего на самом деле хотят многие люди, когда они говорят, что хотят определить, присутствует ли атрибут, OP на самом деле запросил последнее, поэтому разумно, чтобы прямые ответы на этот вопрос (hasattr, AttributeError) были перечислены выше. .

Vexen Crabtree
24 июня 2021 в 11:56
0

Проголосовали за упоминание "свойства по умолчанию". Были времена, когда мне это было нужно, но я забыл об этом!

avatar
nikow
4 марта 2009 в 15:41
14

В зависимости от ситуации вы можете проверить с помощью isinstance, какой у вас объект, а затем использовать соответствующие атрибуты. С введением абстрактных базовых классов в Python 2.6 / 3.0 этот подход также стал намного более мощным (в основном ABC позволяют использовать более сложный способ утиной печати).

Одна ситуация, в которой это было бы полезно, была бы, если бы два разных объекта имели атрибут с одним и тем же именем, но с разным значением. Использование только hasattr может привести к странным ошибкам.

Хороший пример - различие между итераторами и итераторами (см. этот вопрос). Методы __iter__ в итераторе и итераторе имеют одно и то же имя, но семантически совершенно разные! Так что hasattr бесполезен, но isinstance вместе с ABC обеспечивает чистое решение.

Однако я согласен с тем, что в большинстве ситуаций подход hasattr (описанный в других ответах) является наиболее подходящим решением.

avatar
zweiterlinde
4 марта 2009 в 14:56
735

Поскольку ответил Джаррет Харди, hasattr сделает свое дело. Однако я хотел бы добавить, что многие в сообществе Python рекомендуют стратегию «проще просить прощения, чем разрешения» (EAFP), а не «смотреть, прежде чем прыгнуть» (LBYL). См. Эти ссылки:

EAFP против LBYL (Re: пока что немного разочаровал)
EAFP против LBYL @Code Как Pythonista: Идиоматический Python <66804258502>

например:

try:
    doStuff(a.property)
except AttributeError:
    otherStuff()

... предпочтительнее:

if hasattr(a, 'property'):
    doStuff(a.property)
else:
    otherStuff()

jpalecek
14 апреля 2009 в 13:22
302

Но как проверить, что AttributeError вызвало свойство a.property, а не что-то в doStuff ()? Кажется, нет. Я думаю, что действительно проще просить прощения, но во многих случаях это тоже неправильно.

Ethan Heilman
14 октября 2010 в 18:54
332

EAFP кажется ... безумным. HasAttr телеграфирует будущим программистам по обслуживанию, что вы проверяете конкретный атрибут. Получение исключения ничего не говорит будущим программистам и может увести кого-нибудь в кроличью нору.

Max
1 июня 2011 в 13:08
81

@ e5: вы правы в этом случае, но во многих случаях EAFP - единственно правильный вариант. Например, если вы проверяете наличие файла, а затем открываете его, ожидая, что он определенно будет существовать, ваш код неверен: файл может быть удален или переименован между проверкой и использованием. Это называется ошибкой TOCTOU (Time-Of-Check-To-Time-Of-Use) и, помимо сбоев, также может быть источником уязвимостей в системе безопасности.

Peter M. Elias
2 января 2013 в 16:23
19

@EthanHeilman - это безумие только тогда, когда есть двусмысленность в источнике исключения, чего в большинстве случаев можно избежать с помощью хорошего дизайна. Хорошо продуманное структурирование логики внутри try / except / finally обычно обеспечивает более надежную (менее подверженную ошибкам программиста) логику, чем засорение кода упреждающими if-проверками для каждой части потребляющего кода. Также делает ошибки очень явными и позволяет программистам работать с ними напрямую.

Carl Meyer
24 сентября 2013 в 20:21
69

Большинство жалоб на двусмысленность здесь просто потому, что образец кода плохо структурирован. Единственное, что находится внутри try:, - это попытка доступа к атрибуту; нет причин также оборачивать выполнение doStuff. Тем не менее, существует некоторая вероятность двусмысленности: если property является вычисляемым свойством, а не простым атрибутом, его реализация может вызвать внутреннее повышение AttributeError. Вот почему почти во всех реальных ситуациях, подобных этой, getattr предпочтительнее hasattr или перехвата AttributeError.

avatar
Jordan Lewis
4 марта 2009 в 14:56
37

Согласно pydoc, hasattr (obj, prop) просто вызывает getattr (obj, prop) и перехватывает исключения. Таким образом, можно обернуть доступ к атрибуту с помощью оператора try и перехватить AttributeError, как и заранее использовать hasattr ().

a = SomeClass()
try:
    return a.fake_prop
except AttributeError:
    return default_value
odinho - Velmont
18 августа 2011 в 17:37
2

Ну, hasattr на самом деле может быть оптимизирован . Например. с pypy.

Martin Geisler
24 апреля 2013 в 07:47
6

+1. Это даже безопаснее , чем использование hasattr, когда SomeClass переопределяет __getattr__, поскольку hasattr перехватит все исключения в Python182. ожидал бы. Это было исправлено в Python 3.2 - пожалуйста, посмотрите мой другой ответ для простого обходного пути.

avatar
batbrat
4 марта 2009 в 14:52
49

Я думаю, что вы ищете hasattr . Однако я бы порекомендовал что-то подобное, если вы хотите обнаружить свойства python -

try:
    getattr(someObject, 'someProperty')         
except AttributeError:
    print "Doesn't exist"
else
    print "Exists"

Недостатком здесь является то, что ошибки атрибутов в коде свойств __get__ также обнаруживаются.

В противном случае -

if hasattr(someObject, 'someProp'):
    #Access someProp/ set someProp
    pass

Документы :http://docs.python.org/library/functions.html
Предупреждение :
Причина моей рекомендации в том, что hasattr не обнаруживает свойства.
Ссылка: http://mail.python.org/pipermail/python-dev/2005-De December/058498.html

ShadowRanger
25 апреля 2018 в 19:32
3

hasattr в целом отлично определяет свойства. Просто он рассматривает возникновение исключения в функции, обернутой property, как означающее, что такого атрибута не существует; связанное сообщение списка рассылки Python касается свойства, которое вызывает исключение, когда вы пытаетесь получить к нему доступ. Для всех практических целей указанный атрибут не существует, потому что он никогда не будет давать значение. Кроме того, hasattr подавляет исключения только в Py 3.1 и ранее; в 3.2+ он только подавляет (заменяя на False return) AttributeError.