2013-05-03 20 views
7

Bunu yapmanın standart bir yolu olup olmadığından emin değilim. Bir nesnenin tüm içeriğini dökmek için aşağıdaki işlevi uyguladı. Bu yinelemeli alt nesneleri dökümü gerekir, bu yüzden InstanceType kontrol değilim, ama çalışmıyor: Bir elemanın kendisi bir nesne olup olmadığınıBir nesneyi art arda dökülen bir nesne

import types 

def dump_obj(obj, level=0): 
    for a in dir(obj): 
     try: 
      if type(obj.__dict__[a]) == types.InstanceType: 
       dump_obj(obj.__dict__[a], level + 2) 
      else: 
       try: 
        print " " * level + "%s -> %s" % (a, obj.__dict__[a]) 
       except: 
        pass 
     except: 
      pass 

nasıl doğrulanır?

Asıl istediğim şudur: Verilen:

class B: 
    def __init__(self): 
    self.txt = 'bye' 

class A: 
    def __init__(self): 
    self.txt = 'hello' 
    self.b = B() 

a = A() 

dump_obj(a) 

aşağıdaki çıktıyı istiyorum:

txt -> hello 
    txt -> bye 
+0

Her şey Python'da bir nesnedir. – Matthias

+0

Tamam: Bir elemanın types.InstanceType' olup olmadığını nasıl doğrulayabilirim (veya gerekli olan her şey), böylece yinelemeyi tetikleyebilir miyim? – dangonfast

cevap

2

O isinstance(x, y) yerine type(x) == y kullanmak her zaman daha iyidir.

Her şey Python'da bir nesne olduğu için, isinstance(attr, object) yapmak mantıklı değildir, çünkü (sanırım) her zaman doğru döner.

En iyi bahsiniz, belirli türleri "kara listeye almak". Örneğin, int, float, str, unicode, list, dict, set, ...'dan başka bir şey olup olmadığını kontrol edersiniz, aksi halde yazdırırsınız.

def dump(obj, level=0): 
    for attr in dir(obj): 
     val = getattr(obj, a) 
     if isinstance(val, (int, float, str, unicode, list, dict, set)): 
      print level*' ', val 
     else: 
      dump(val, level=level+1) 

GÜNCELLEME: Örneğin

isinstance hesap miras dikkate alır, bu nedenle bir nesne bir üst sınıfının bir örneğidir olup olmadığını görmek için çalışırsanız, True dönecektir ederken değilken may türünü kullanma.

Bu durumda ilkel türlere karşı test edeceğinizden, bu durumda herhangi bir fark yaratmayabilir, ancak genel olarak isinstance tercih edilir.

bu örneğe bakın:

>>> class A(object): pass 
... 
>>> class B(A): pass 
... 
>>> a, b = A(), B() 
>>> type(a) 
<class '__main__.A'> 
>>> type(a) == A 
True 
>>> type(b) 
<class '__main__.B'> 
>>> type(b) == B 
True 
>>> type(b) == A 
False 
>>> 

Dışarı şeyler yanlış sırayla (basılmış olsun dışında Kodunuz, benim için çalışıyor docs

+0

Teşekkürler, buna benzer bir şey yapmayı bitirdim, ancak 'type() ==' kullanarak. "Isinstance" ın kullanılmasının neden daha iyi olduğunu açıklar mısınız? – dangonfast

+0

Haklısınız ve örneğim sadeleştirilmişti: aslında karmaşık kütüphaneleri standart kütüphanelerden almak istiyorum, bu yüzden uyarınız alakalı. Öte yandan, 'getattr' da sonsuz özyönüllülüğe neden olan yöntemleri ve diğer şeyleri döndürür. – dangonfast

+0

@gonvaled Oh güzel bulmak :) – jadkik94

5

kontrol edebilirsiniz benim asıl olur, ilk iç hangi tekrarlama ile beklemek).

Yani, sipariş değiştirildi (ve __dict__ üzerinde iterating yanı sıra isinstance() kullanılır):

import types 

def dump_obj(obj, level=0): 
    for key, value in obj.__dict__.items(): 
     if not isinstance(value, types.InstanceType): 
      print " " * level + "%s -> %s" % (key, value) 
     else: 
      dump_obj(value, level + 2) 

class B: 
    def __init__ (self): 
    self.txt = 'bye' 

class A: 
    def __init__(self): 
    self.txt = 'hello' 
    self.b = B() 

a = A() 

dump_obj(a) 

yinelemeli herhangi bir nesne ve tüm alt nesneleri dökümü

txt -> hello 
    txt -> bye 
+0

Bu basit örnekler için çalıştı, ancak karmaşık bir nesne için, bazı verilerde eksikti alt nesneler. – wisbucky

5

Bu üretir. Diğer cevaplar basit örnekler için çalıştı, ancak karmaşık nesneler için bazı veriler eksikti.

import jsonpickle # pip install jsonpickle 
import json 

serialized = jsonpickle.encode(obj) 
print json.dumps(json.loads(serialized), indent=2) 

DÜZENLEME: YAML biçimini kullanırsanız, örneğinize daha yakın olacaktır.

import yaml # pip install pyyaml 
print yaml.dump(yaml.load(serialized), indent=2) 
+2

bu kabul edilen cevap olmalı –

İlgili konular