Python'da bir nesnenin özellikleri nasıl numaralandırılır?


133

IC # bunu yansıtma yoluyla yapıyoruz. Javascript'te şu kadar basit:

for(var propertyName in objectName)
    var currentPropertyValue = objectName[propertyName];

Python'da nasıl yapılır?



3
Lütfen bu sorunun yanlış bir isim olduğunu unutmayın. Cevapların çoğu, üyeleri sıralamakla ilgilidir . Özellikleri , yani dekore edilmiş bir sınıfın üyelerini sıralamanın bir yolunu arıyordum @property.
Tomasz Gandor

Yanıtlar:


153
for property, value in vars(theObject).iteritems():
    print property, ": ", value

Bazı ender durumlarda __slots__, bir özellik bulunduğunu, bu tür sınıfların çoğu zaman hiç olmadığını unutmayın __dict__.


1
şimdi değeri nasıl değiştirebilirim? Javascript'te şunları yapabilirsiniz: object [property] = newValue. Python'da nasıl yapılır?
Jader Dias

39
bunun yerine setattr () kullanın.
Nelson

1
@Nelson Bunun neden daha iyi bir seçenek olduğunu açıklayabilir misiniz? Daha kısa mı yoksa ek hususlar var mı?
WhyNotHugo

8
@Hugo: Birincisi, "pitonik" olduğu için, başka bir deyişle, topluluğun büyük çoğunluğunun görmeyi beklediği sözdizimi bu. Diğer sözdizimi, kodunuzu okuyan herhangi birini büyük olasılıkla gereksiz yere duraklatacaktır. İkinci olarak, bazı türler bir pasör uygular __setattr__(). Değerleri doğrudan sözlük üzerinden ayarlamak, nesnenin ayarlayıcısını (ve / veya üst öğelerini) atlar. Python'da, öznitelik ayarı (örneğin sanitasyon) sırasında arka planda gözle görmekten çok daha fazla şeyin gerçekleşmesi oldukça yaygındır, kullanmak setattr(), bunları kaçırmamanızı veya bunları açıkça kendiniz işlemeye zorlanmanızı sağlar.
Michael Ekoka

3
Hi-Melek @ O does işi. Bununla birlikte, işe yaramayan şey, Python'daki dinamik nesne üyelerine karşı çevrenizdeki önyargıların ve varsayımların bir takımyıldızıdır. vars()yalnızca statik üyeler döndürür (yani, nesne öznitelikleri ve o nesneye kaydedilmiş yöntemler __dict__). O mu değil dönmek dinamik üyeleri (dinamik olarak o nesnenin tanımladığı, yani nesne özelliklerini ve yöntemlerini __getattr__()yöntemiyle veya benzer büyü). Büyük olasılıkla, istediğiniz file.ImplementationNameözellik dinamik olarak tanımlanan ve dolayısıyla değil mevcut vars()veya dir().
Cecil Curry

69

Bakın inspect.getmembers(object[, predicate]).

Ada göre sıralanmış (ad, değer) çiftleri listesinde bir nesnenin tüm üyelerini döndürür. İsteğe bağlı yüklem bağımsız değişkeni sağlanırsa, yalnızca yüklemenin gerçek bir değer döndürdüğü üyeler dahil edilir.

>>> [name for name,thing in inspect.getmembers([])]
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', 
'__delslice__',    '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', 
'__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', 
'__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__','__reduce_ex__', 
'__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', 
'__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 
'insert', 'pop', 'remove', 'reverse', 'sort']
>>> 

Evet, bu cevap harika; bu modülü daha önce hiç kullanmadım. getmembers (), dir (object), btw'nin sonuçları yürünerek gerçekleştirilir.
Nelson

Bunun neden dikte erişmekten daha iyi olduğunu açıklayabilir misiniz ? Python dokümantasyonu yararlı olmaktan daha azdır, özellikle normalde attributesyerine terimi kullandığı için members(ikisi arasında herhangi bir fark var mı?). Tutarlı hale getirmek için Python 3.0'da adı sabitleyebilirlerdi.
nikow

__dict__Üzgünüm demek istedim.
nikow

4
@nikow: inspect.getmembers (), dahili ayrıntılar değişse bile çalışmaya devam eder.
Georg Schölly

3
@NicholasKnight inspect.getmembers()sargıları dir()arasında (çoğunlukla ihmal edilebilir) bir yan fayda (A) dahil olmak üzere, dinamik sınıfı öznitelikleri ve metaclass nitelikleri ve (B) ' hariç üye olup geçirilen yüklemi bulundu. Esnemek, değil mi? inspect.getmembers()olası tüm nesne türlerini genel olarak destekleyen üçüncü taraf kitaplıkları için uygundur. Ancak standart kullanım durumları için dir()kesinlikle yeterlidir.
Cecil Curry

66

dir()basit bir yoldur. Buraya bakın:

Python Introspection Kılavuzu


2
Python belgelerinden not edilmesi gereken bir şey, dir () öncelikle etkileşimli bir komut isteminde kullanım kolaylığı olarak sağlandığından, titizlikle veya tutarlı bir şekilde tanımlanmış bir isim kümesi sağlamaya çalışmaktan daha fazla ilginç bir isim kümesi sağlamaya çalışır ve ayrıntılı davranışı sürümler arasında değişebilir. Örneğin, bağımsız değişken bir sınıf olduğunda meta sınıf öznitelikleri sonuç listesinde bulunmaz.
skyler

1
bu cevap, cli üzerinde sıfırdan çalışma yaparken en iyisidir.

15 yıllık python (hiç tam zamanlı iş değil) ve yine de dir()teşekkür ederim unutuyorum .
Abhishek Dujari

14

__dict__Nesnenin özelliği tüm diğer tanımlanmış özelliklerin bir sözlüktür. Python sınıflarının getattr'ı geçersiz kılabileceğini ve özellikler gibi görünen ama içinde olmayan şeyler yapabileceğini unutmayın __dict__. Ayrıca yerleşik işlevleri var vars()ve dir()ince şekilde farklıdır. Ve bazı alışılmadık sınıflarda __slots__yerini alabilir __dict__.

Python'da nesneler karmaşıktır. __dict__yansıtma tarzı programlamaya başlamak için doğru yerdir. dir()etkileşimli bir kabukta geziniyorsanız başlamanız gereken yerdir.


print vars.__doc__olduğunu gösterir With an argument, equivalent to object.__dict__Yani ince farklar ne olurdu?
sancho.s ReinstateMonicaCellio


10

Tüm özelliklerin yansımasını arıyorsanız, yukarıdaki cevaplar harika.

Bir sözlüğün anahtarlarını (Python'daki bir 'nesneden' farklı olan) almak istiyorsanız, şunu kullanın:

my_dict.keys()

my_dict = {'abc': {}, 'def': 12, 'ghi': 'string' }
my_dict.keys() 
> ['abc', 'def', 'ghi']

1
cevabım olmasına rağmen, bunun kabul edilen cevap olması gerektiğini düşünmüyorum: Bir nesnenin anahtarları, bir sınıfın nesne örneğinin özelliğinden farklıdır. Bunlara farklı şekilde erişilir ( obj['key']vs. obj.property) ve soru nesne özellikleri hakkındaydı. Cevabımı buraya koyuyorum çünkü ikisi arasında kolay kafa karışıklığı var.
MrE

Aslında bu cevabı kaldırmanızı öneririm.
Ente

Yukarıda belirtildiği gibi, örneğin Javascript veya C # 'dan gelen kişiler, bu 2 kavram arasında hiçbir fark olmadığı için terminoloji ile kolayca karıştırılır. Python öğrenen ve anahtarlara erişmeye çalışan insanlar büyük olasılıkla 'özellikler' arayacak ve buraya gelecektir, bu yüzden onun ait olduğunu düşünüyorum.
MrE

ve haklısın, ama asıl noktayı kaçırıyorsun: diğer dillerde (JS'yi al) nesne ve sözlük arasında bir ayrım yok. OP, soruyu soran C # dan gelir. Bu cevap, yanlış olmasına rağmen, 11 olumlu oy aldı, bu, teknik olarak soruya katı python dilinde bakıldığında (işaret ettiğim gibi) teknik olarak doğru cevap olmasa da, buraya gelen insanların onu faydalı bulduklarının kanıtı. Daha da net hale getirmek için düzenleyeceğim.
MrE

5

Bu tamamen diğer cevaplar tarafından kapsanmaktadır, ancak açıklayacağım. Bir nesnenin sınıf öznitelikleri ve statik ve dinamik örnek öznitelikleri olabilir.

class foo:
    classy = 1
    @property
    def dyno(self):
        return 1
    def __init__(self):
        self.stasis = 2

    def fx(self):
        return 3

stasisstatiktir, dynodinamiktir (cf. özellik dekoratörü) ve classybir sınıf özniteliğidir. Basitçe yaparsak __dict__ya varsda sadece statik olanı alırız.

o = foo()
print(o.__dict__) #{'stasis': 2}
print(vars(o)) #{'stasis': 2}

Yani istersek diğerleri __dict__her şeyi (ve daha fazlasını) alır. Bu, sihirli yöntemleri ve nitelikleri ve normal bağlı yöntemleri içerir. Öyleyse bunlardan kaçınalım:

d = {k: getattr(o, k, '') for k in o.__dir__() if k[:2] != '__' and type(getattr(o, k, '')).__name__ != 'method'}
print(d) #{'stasis': 2, 'classy': 1, 'dyno': 1}

typeBir özellik dekore yöntemi (dinamik nitelik) ile adlandırılan, size iade değerin türünü değil verecektir method. Bunu kanıtlamak için json bunu telafi edelim:

import json
print(json.dumps(d)) #{"stasis": 2, "classy": 1, "dyno": 1}

Bir yöntem olsaydı çökerdi.

TL; DR. extravar = lambda o: {k: getattr(o, k, '') for k in o.__dir__() if k[:2] != '__' and type(getattr(o, k, '')).__name__ != 'method'}üçünü de aramayı deneyin , ancak yöntemleri veya sihri değil.

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.