2013-04-22 17 views
5

Arabirimi temsil eden bir özet taban sınıfım var. Bu sınıfın alt sınıfları, bu sınıfın diğer alt sınıflarının özellikleri olarak saklanır. Örneğinİç içe geçmiş sınıf örnekleri için yararlı varsayılan __repr__

:

class AbstractBase(object): 
    pass 

class Child(AbstractBase): 
    def __init__(self, cls1, cls2): 
     assert isinstance(cls1, AbstractBase) 
     assert isinstance(cls2, AbstractBase) # just to show they're instances 

     self.cls1 = cls1 
     self.cls2 = cls2 

hiyerarşi derinliği ve düzen önceden bilinemez, ama özyinelemeli olmayacaktır.

__repr__ ürününü AbstractBase numaralı telefona ne koyabilirim ki, her bir alt sınıfın önerilerini yararlı bir şekilde görmeme izin verecek?

Benim şu anki yaklaşımdır:

MyClass 
{'var1': 1, 
'var2': 2} 

Ancak sınıflar için AbstractBase ile: AbstractBase alt sınıfları olan hiçbir özelliklere sahip

bir temel sınıf için
from pprint import pformat 

class AbstractBase(object): 
    def __repr__(self): 
     return self.__class__.__name__ + '\n' \ 
       + pformat({k:v for k,v in self.__dict__.iteritems() 
          if not '__' in k}) 

(bu okunabilir bir şey, örneğin çıkışı alt sınıflar kırılır, çünkü bir ana sınıfın nerede başladığını ve bir başka sona erdiğini söylemek zordur (yukarıdaki __repr__ tarafından daha fazla girintileme yapılmadığı göz önüne alınırsa)

Ben cls1 ve cls2 tek int özelliği var vardı hayal aşağıda gibi bir şeyle mutlu olurum: Ne yazık ki

Child 
{'cls1': { 
      'var': 1, 
     }, 
'cls2': { 
      'var': 0, 
     } 
} 

, bunu başarmak için nasıl biliyor (ya da hatta mümkünse) yok . Düşüncesi olan var mı?

+2

Sen gibi bir şey istemek' def __repr __ (self, girinti = 1) ', bazı garip köşe olacak –

cevap

2

Ben bu şekilde yapıyor ne var gibi:

class AbstractBase(object): 
    def __repr__(self, indent=2): 
     result = self.__class__.__name__ + '\n' 
     for k,v in self.__dict__.iteritems(): 
      if k.startswith('__'): 
       continue 
      if isinstance(v, AbstractBase): 
       vStr = v.__repr__(indent + 2) 
      else: 
       vStr = str(v) 
      result += ' '*indent + k + ': ' + vStr 
     result += '\n' 
     return result 
+0

'u kapsayamayacak durumlar bu yanıtı beğeniyorum. Dizileri hesaba katmak için biraz değiştirdim ve (daha ne olduğunu düşünüyorum) biraz daha okunabilir bir çıktı yazdı - cevabımı görün. Hiç kimse başka bir parlaklık vuruşuna sahip değilse birkaç gün içinde kabul edeceğim :) – sapi

0

Bu John Zwinck önerdiği şeyin biraz değiştirilmiş bir versiyonudur.

Dizilerin nasıl biçimlendirileceğini ve biçimin biraz değiştirileceğini düşünür. Şu anda mükemmel değil - özellikle yinelenen bileşen yalnızca anahtarı basacağı için özellikle sözlükler için ayrılacak. Orada kendi bir sigara sar zorunda pformat` `ile birleştirmek için bir yol muhtemelen ve olsa

def __repr__(self, indent=2): 
     result = self.__class__.__name__ + '\n' 
     items = self.__dict__.items() 

     for i,(k,v) in enumerate(items): 
      if '__' in k: 
       continue  
      if isinstance(v, AbstractBase): 
       vStr = '\n' + ' '*(indent + 2) + v.__repr__(indent + 4) 
      elif isinstance(v, collections.Iterable): 
       s = str(v) 
       bstart = s[0] 
       bend = s[-1] 

       newIndent = indent + 3 
       vStr = '\n' + ' '*(newIndent - 1) + bstart 
       for j,item in enumerate(v): 
        if isinstance(item, AbstractBase): 
         if j: 
          vStr += ' '*newIndent 
         vStr += item.__repr__(newIndent + 2) 
        else:  
         vStr += repr(item) 
        vStr += ',\n' 
       vStr += ' '*(newIndent - 1) + bend 
      else:    
       vStr = str(v) 
      result += ' '*indent + k + ': ' + vStr 

      if i != len(items) - 1: 
       result += '\n' 

     result = re.sub('\n+', '\n', result) 
     return result 
İlgili konular