Bir nesnenin Python'da bir özniteliği olup olmadığını bilmek


1635

Python'da bir nesnenin bazı nitelikleri olup olmadığını belirlemenin bir yolu var mı? Örneğin:

>>> 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Özniteliği propertykullanmadan önce olup olmadığını nasıl anlarsınız ?

Yanıtlar:


2340

Deneyin hasattr():

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

DÜZENLEME: Affetme istemekle ilgili iyi tavsiyeler sunan zweiterlinde'nin cevabını aşağıda görebilirsiniz! Çok pitonik bir yaklaşım!

Python'daki genel uygulama, eğer özellik çoğu zaman orada olacaksa, sadece onu arayın ve istisnanın yayılmasına izin verin veya bir dene / hariç bloğu ile yakalayın. Bu muhtemelen daha hızlı olacaktır hasattr. Mülk çoğu zaman orada olmayacaksa veya emin değilseniz, kullanmak hasattrtekrar tekrar bir istisna bloğuna düşmekten daha hızlı olacaktır.


19
İsim alanındaki işlevleri de kontrol etmek için çalışıyor gibi görünüyor, örneğin: import string hasattr(string, "lower")
riviera

15
hasattraynen kullanarak aynıdır try/ except AttributeError: hasattr docstring'ini (Python 2.7 olarak) o getattr eli yakalar istisnalar kullandığını söylüyor.
Jeff Tratner

8
@JeffTratner: hasattrmaalesef değil tam bir aynı try: ... except AttributeError:beri Python 2.x hasattrolacak tüm özel durum yakalamak . Bakınız Cevabımı bir örnek ve basit bir çözüm için.
Martin Geisler

1
@MartinGeisler İyi bir nokta - tüm istisnaları yakalamakla aynı şey değil. Hangi sürümün daha doğru olduğundan emin değilim - gerçekten altında çalıştığınız varsayımlara ve işlevinizi kimin aradığına bağlıdır. Açıkladığınız için teşekkürler.
Jeff Tratner

2
hasattrEğer bir kavrayışta iseniz, aynı zamanda üstün bir seçimdir, örneğin[a.property for a in list_of_as if hasattr(a, "property")]
Rafael Martins

632

As Jarret Hardie cevap, hasattrhile olacaktır. Yine de, Python topluluğunun birçoğunun "sıçramadan önce bak" (LBYL) yerine "izinten daha affetmeyi istemek" (EAFP) stratejisini önerdiğini eklemek isterim. Şu referanslara bakın:

EAFP vs LBYL (Re: Şimdiye kadar biraz hayal kırıklığına uğradım)
EAFP vs LBYL @Code Pythonista gibi: Deyimsel Python

yani:

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

... aşağıdakiler için tercih edilir:

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

257
Ancak doStuff () öğesinde bir şeyin değil AttributeError'a neden olan a.property olup olmadığını nasıl kontrol edersiniz? Görünmüyor gibi. Affetmek gerçekten daha kolay olduğunu düşünüyorum, ancak birçok kez de yanlış.
jpalecek

283
EAFP ... deli gibi görünüyor. HasAttr, belirli bir özelliği kontrol ettiğiniz gelecekteki bakım programcılarına telgraflar. Bir istisna almak gelecekteki programcılara hiçbir şey söylemez ve birisini tavşan deliğinden aşağı çekebilir.
Ethan Heilman

74
@ e5: bu durumda adil bir noktanız var, ancak çoğu durumda EAFP tek doğru seçenektir. Örneğin, bir dosyanın varlığını kontrol edip açarsanız, kesinlikle varolmasını beklerseniz, kodunuz yanlıştır: dosya, kontrol ile kullanım arasında silinebilir veya yeniden adlandırılabilir. Buna TOCTOU hatası (Kullanım Zamanı-Kontrol-Kullanım Zamanı) denir ve çökmelere neden olmasının yanı sıra güvenlik açıklarının kaynağı da olabilir.
Max

15
@EthanHeilman, istisna kaynağında belirsizlik olduğunda, çoğu durumda iyi bir tasarımla önlenebiliyorsa deliriyor. Deneme / hariç / son olarak mantığın iyi bir şekilde yapılandırılması, her tüketen kod parçası için önleyici if-kontrolleri ile kodun altından daha sağlam (daha az programcı hatası eğilimli) mantık oluşturur. Hataları da çok açık hale getirir ve programcıların doğrudan onlarla başa çıkma seçeneğini kullanmalarına izin verir.
Peter M. Elias

64
Buradaki belirsizlik şikayetlerinin çoğu, örnek kodun kötü yapılandırılmış olmasından kaynaklanmaktadır. İçindeki tek şey try:, girişilen öznitelik erişimi olmalıdır; idamını da sarmak için bir sebep yok doStuff. Yine de bazı belirsizlik potansiyeli vardır: eğer propertydüz bir özellik yerine hesaplanmış bir özellik ise, uygulaması AttributeErrordahili olarak artabilir. Bu yüzden bunun gibi hemen hemen tüm gerçek durumlarda, ya yakalamak getattrya hasattrda yakalamak tercih edilir AttributeError.
Carl Meyer

485

Kullanabilir hasattr()veya yakalayabilirsiniz AttributeError, ancak gerçekten yoksa, özelliğin değerini varsayılan olarak istiyorsanız, en iyi seçenek sadece kullanmaktır getattr():

getattr(a, 'property', 'default value')

14
Bu her iki sorunu da çözmektedir: a) Olası bir AttributeError kaynağının belirsizliği, b) EAFP yaklaşımının korunması.
Peter M. Elias

6
Ayrıca kod satırlarının% 25'i. Elbette bu en iyi çözüm olmalıdır.
fatuhoku

16
Bu, "özelliğin değerini bir varsayılan değerle gerçekten istiyorsanız" en iyi çözümdür. Her ne kadar birçok insanın bir özniteliğin var olup olmadığını tespit etmek istediklerini söylediklerine inanmasına rağmen, OP aslında ikincisini istedi, bu nedenle bu soruya doğrudan cevapların (hasattr, AttributeError) daha yüksek listelenmesi makul .
Carl Meyer

41

Bence aradığın şey hasattr . Ancak, python özelliklerini tespit etmek istiyorsanız böyle bir şey öneriyorum -

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

Buradaki dezavantaj, özellikler __get__kodundaki öznitelik hatalarının da yakalanmasıdır.

Aksi takdirde,

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

Dokümanlar: http://docs.python.org/library/functions.html
Uyarı:
Tavsiyemin nedeni hasattr'ın özellikleri algılamaması.
Bağlantı: http://mail.python.org/pipermail/python-dev/2005-Aralık/058498.html


yani, tavsiyeniz buil-in değil - uygulayın!
SilentGhost

Tam olarak değil, özellikleri tespit etmek istediğiniz yerleşik IFF'yi kullanmayın. Aksi takdirde hasattr mükemmel derecede iyidir.
batbrat

3
hasattrözellikleri gayet iyi algılar. Sadece property-wrapped işlevinde bir istisna oluşturmayı böyle bir niteliğin olmadığı anlamına gelir; bağlantılı Python posta listesi gönderisi, erişmeye çalıştığınızda bir istisna oluşturan bir özellik hakkındadır. Tüm pratik amaçlar için, bahsedilen özellik mevcut değildir, çünkü asla bir değer üretmez. Ayrıca, hasattrsadece genel olarak Py 3.1 ve önceki sürümlerdeki istisnaları bastırır; 3.2 + 'da, sadece bastırır ( Falsegeri dönüşle değiştirerek ) AttributeError.
ShadowRanger

32

Pydoc'a göre, hasattr (obj, prop) sadece getattr (obj, prop) çağırır ve istisnaları yakalar. Bu nedenle, öznitelik erişimini bir try ifadesiyle sarmak ve önceden hasattr () kullanmak gibi AttributeError'ı yakalamak da geçerlidir.

a = SomeClass()
try:
    return a.fake_prop
except AttributeError:
    return default_value

2
Eh hasattr aslında edilebilir optimize. Örneğin pypy ile.
odinho - Velmont

6
+1. Bu bile olduğunu daha güvenli kullanmak yerine hasattrne zaman SomeClassgeçersiz kılar __getattr__beri hasattryakalayacak tüm değil sadece, Python 2.x istisnalar AttributeErrorbeklediğiniz gibi. Bu Python 3.2'de düzeltildi - lütfen basit bir çözüm için diğer cevabıma bakın.
Martin Geisler

24

Bunu önlemek için önermek istiyorum:

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

@Jpalecek kullanıcısı bundan bahsetti: AttributeErrorİçinde bir olay olursa doStuff()kaybolursunuz.

Belki bu yaklaşım daha iyidir:

try:
    val = a.property
except AttributeError:
    otherStuff()
else:
    doStuff(val)

sadece olabilir: try: a.propertysol tarafa gerek yok
Petruza

Sonra başka bir blokta bir mülkü tekrarlamanız gerekir ve bu başarısız olabilir.
Éric Araujo

13

Duruma bağlı olarak, isinstancene tür bir nesneye sahip olduğunuzu kontrol edebilir ve ardından ilgili nitelikleri kullanabilirsiniz. Soyut temel sınıfların tanıtımı ilePython 2.6 / 3.0'da bu yaklaşım çok daha güçlü hale geldi (temel olarak ABC'ler ördek yazmanın daha sofistike bir yolunu sağlar).

Bir durum, iki farklı nesnenin aynı ada sahip, ancak farklı bir anlama sahip olması durumunda faydalı olacağı bir durumdur. Yalnızca kullanmahasattr garip hatalara yol açabilir.

Güzel bir örnek, yineleyiciler ve yinelenebilirler arasındaki ayrımdır ( bu soruya bakın ). __iter__Bir yineleyici içinde yöntemleri ve iterable aynı ada sahip aynı anlama oldukça farklı olduğu bir! Bu hasattrişe yaramaz, ancak isinstanceABC'lerle birlikte temiz bir çözüm sağlar.

Ancak, çoğu durumda hasattryaklaşımın (diğer cevaplarda açıklanan) en uygun çözüm olduğunu kabul ediyorum .


13

Hasat () bekliyoruz, ancak hasattr () kaçının ve lütfen getattr () tercih edin. getattr (), hasattr () 'dan daha hızlıdır

hasattr () kullanarak:

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

aynı burada hiçbir özelliği varsa hiçbir özellik döndürmek için getattr kullanıyorum

   property = getattr(a,"property",None)
    if property:
        print property

11

EDIT : Bu yaklaşımın ciddi bir sınırlaması vardır. Nesne yinelenebilir bir nesne ise çalışmalıdır . Lütfen aşağıdaki yorumları kontrol edin.

Benim gibi Python 3.6 veya daha üstünü kullanıyorsanız , bir nesnenin belirli bir niteliğe sahip olup olmadığını kontrol etmek için uygun bir alternatif vardır:

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

Ancak şu anda en iyi yaklaşımın hangisi olduğundan emin değilim. kullanma hasattr(), kullanma getattr()veya kullanma in. Yorumlarınızı bekliyoruz.


6
inanahtar kelime yinelenebilir türleri kontrol etmek için çalışır. Örneğin 'foo' in None, hatayı atar TypeError: argument of type 'NoneType' is not iterable. Düzeltme, kullanmadan önce türün yinelenebilir olup olmadığını kontrol etmektir in. Yinelenemeyen tip gibi kenar durumlarını düzelttikten sonra hasattr(), kenar durumlarını işlemek için tasarlandığından muhtemelen daha iyi durumda olursunuz .
Seth Difley

3
Bunun özellik erişimi ile ilgisi yoktur. Nasıl değerlendirildiğine dair hiçbir fikrim yok. Erişimi ilişkilendirmek için tek benzerliği dict, JavaScript nesnelerinin tasarımına benzer bir "hafif nesne" olarak kullanmanızdır , ancak normal sınıfların çoğu bunu genel olarak desteklemez (@SethDifley tarafından belirtilen hataya bir varyant almak) .
ShadowRanger

2
Eğer sınıfta 'değişken' ise. dict__: ??
Ben


1

Bu çok basit, sadece dir(nesneyi kullan Nesnenin)
kullanılabilir tüm işlevlerinin ve özniteliklerinin bir listesini döndürür.


1

Başka bir olası seçenek, ancak daha önce ne demek istediğinize bağlı olarak değişir :

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

çıktı:

bar:1
zoom!

Bu, Hiçbiri değerli nitelikleri bile kontrol etmenizi sağlar.

Fakat! undefinedBirden fazla yeri kazara başlatmamaya ve karşılaştırmamaya çok dikkat edin, çünkü isbu durumda asla çalışmayacaktır.

Güncelleme:

Yukarıdaki paragrafta neyle ilgili olduğumdan dolayı, asla eşleşmeyen birden fazla tanımsız olması nedeniyle, bu kalıbı son zamanlarda biraz değiştirdim:

undefined = NotImplemented

NotImplementedile karıştırılmamalıdır NotImplementedError, yerleşiktir: bir JS'nin niyetiyle yarı eşleşir undefinedve tanımını her yerde yeniden kullanabilirsiniz ve her zaman eşleşir. Dezavantajları booleans "doğrudur" ve günlükleri ve yığın izleri tuhaf görünebilir (ama sadece bu bağlamda göründüğünü bildiğinizde hızla aşmak).


0

Builtin yöntemini objectkullanarak öznitelik içerip içermediğini kontrol edebilirsiniz hasattr.

Örneğin, nesneniz öyleyse ave niteliği kontrol etmek istiyorsanızstuff

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

İmzalar kendisi hasattr(object, name) -> boolise olan ortalama objectsahip özelliği ikinci değişken geçirilir hasattrbu mantıksal verir daha Trueveya Falsevarlığına göre namenesne öznitelik.


0

hasattr()doğru cevaptır. Ne eklemek istiyorum hasattr()da iyi assert ile birlikte kullanılabilir (gereksiz ififadeleri önlemek ve kodu daha okunabilir yapmak için):

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

SO ile ilgili başka bir cevapta belirtildiği gibi : Ekler, asla olmaması gereken koşulları test etmek için kullanılmalıdır. Amaç, programın bozuk olması durumunda erken çökmektir.


Bu yardımcı olur, ancak her zaman böyle olmayabilir. Belki nesnenin bir özelliği olup olmadığını test etmek ve daha sonra ilk kez eklemek istedim, ya da belki bu özelliği olan nesneler için farklı kod çalıştırmak zorunda. Kod devam edemediğinde iddia doğru olabilir. Ama yine de, her zaman böyle değildir. Önemli hasattrolan çevreleyen kodun kullanılmamasıdır.
Lucas Gabriel Sánchez
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.