Jak sprawdzić, czy obiekt ma atrybut w Pythonie

Czy istnieje sposób w Pythonie, aby określić, czy obiekt ma jakiś atrybut? Na przykład:

>>> 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'

Jak możesz sprawdzić, czy a ma atrybut property przed użyciem?

Author: Dana, 2009-03-04

9 answers

Spróbuj hasattr():

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

EDIT: Zobacz odpowiedź zweiterlinde poniżej, który oferuje dobrą radę o proszeniu o przebaczenie! Bardzo pythoniczne podejście!

Ogólna praktyka w Pythonie polega na tym, że jeśli właściwość prawdopodobnie będzie tam przez większość czasu, po prostu wywołaj ją i albo pozwól, aby wyjątek rozprzestrzeniał się, albo pułapkuj ją blokiem try / except. Będzie to prawdopodobnie szybsze niż hasattr. Jeśli nieruchomość prawdopodobnie nie będzie tam przez większość czasu, lub nie jesteś pewien, za pomocą hasattr będzie prawdopodobnie szybsze niż wielokrotne wpadanie w blok WYJĄTKÓW.

 1659
Author: Jarret Hardie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-21 19:26:12

Jak odpowiedział Jarret Hardie, to da radę. Chciałbym jednak dodać, że wielu w społeczności Pythona zaleca strategię "łatwiej prosić o przebaczenie niż pozwolenie" (EAFP), a nie "spójrz, zanim skoczysz" (LBYL). Zobacz te referencje:

EAFP vs LBYL (był Re: na razie trochę rozczarowany)
EAFP vs. Lbyl @Code Like A Pythonist: Idiomatic Python

Ie:

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

... jest preferowany do:

if hasattr(a, 'property'):
    doStuff(a.property)
else:
    otherStuff()
 476
Author: zweiterlinde,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-27 09:30:53

Możesz użyć hasattr() lub catch AttributeError, ale jeśli naprawdę chcesz, aby wartość atrybutu była domyślna, jeśli jej nie ma, najlepszą opcją jest użycie getattr():

getattr(a, 'property', 'default value')
 383
Author: Carl Meyer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-24 20:22:25

Myślę, że to, czego szukasz, to hasattr . Jednak polecam coś takiego, jeśli chcesz wykryć właściwości Pythona-

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

Wadą jest to, że błędy atrybutów w kodzie właściwości __get__ są również przechwytywane.

W Przeciwnym Razie do-

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

Docs: http://docs.python.org/library/functions.html
Warning:
Powodem mojej rekomendacji jest to, że hasattr nie wykrywa właściwości.
Link: http://mail.python.org/pipermail/python-dev/2005-December/058498.html

 35
Author: batbrat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-04 15:29:11

Według pydoc, hasattr(obj, prop) po prostu wywołuje getattr (obj, prop) i wychwytuje wyjątki. Tak samo ważne jest owinięcie atrybutu access instrukcją try i przechwycenie AttributeError, jak wcześniejsze użycie metody hasattr ().

a = SomeClass()
try:
    return a.fake_prop
except AttributeError:
    return default_value
 27
Author: Jordan Lewis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-04 14:56:26

Chciałbym zasugerować unikanie tego:

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

Użytkownik @ jpalecek wspomniał o tym: Jeśli AttributeError występuje wewnątrz doStuff(), jesteś zagubiony.

Może to podejście jest lepsze:

try:
    val = a.property
except AttributeError:
    otherStuff()
else:
    doStuff(val)
 14
Author: Maico,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-26 13:04:30

W zależności od sytuacji możesz sprawdzić za pomocą isinstance jaki masz obiekt, a następnie użyć odpowiednich atrybutów. Wraz z wprowadzeniem abstrakcyjnych klas bazowych w Pythonie 2.6/3.0 podejście to stało się również znacznie potężniejsze (zasadniczo ABC pozwalają na bardziej wyrafinowany sposób pisania kaczek).

Jedna sytuacja, w której jest to użyteczne, byłaby taka, gdyby dwa różne obiekty miały atrybut o tej samej nazwie, ale o innym znaczeniu. Używanie tylko hasattr może wtedy prowadzić do dziwnych błędów.

Miłym przykładem jest rozróżnienie pomiędzy iteratorami i iterabami (zobacz to pytanie). Metody __iter__ w iteratorze i iterable mają tę samą nazwę, ale są semantycznie zupełnie inne! Więc {[1] } jest bezużyteczny, ale isinstance RAZEM Z ABC zapewnia czyste rozwiązanie.

Zgadzam się jednak, że w większości sytuacji najodpowiedniejszym rozwiązaniem jest podejście hasattr (opisane w innych odpowiedziach).

 11
Author: nikow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:34

EDIT: takie podejście ma poważne ograniczenia. Powinno działać, jeśli obiekt jest iterowalny . Proszę sprawdzić komentarze poniżej.

Jeśli używasz Pythona 3.6 lub wyższego jak ja, istnieje wygodna alternatywa, aby sprawdzić, czy obiekt ma określony atrybut:

if 'attr1' in obj1:
    print("attr1 = {}".format(obj1["attr1"]))
Nie jestem jednak pewien, które podejście jest teraz najlepsze. używając hasattr(), używając getattr() lub używając in. Komentarze są mile widziane.
 10
Author: nayak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-26 08:54:31

Mam nadzieję, że spodziewasz się hasattr (), ale staraj się unikać hasattr() i preferuj getattr (). getattr () jest szybsze niż hasattr ()

Korzystanie z hasattr():

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

To samo tutaj używam getattr aby uzyskać Właściwość jeśli nie ma właściwości zwraca none

   property = getattr(a,"property",None)
    if property:
        print property
 9
Author: Janarthanan Ramu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-22 05:47:18