Python 嵌套类实例的有用默认值
我有一个表示接口的抽象基类。该类的子类作为属性存储在该类的其他子类中 例如:Python 嵌套类实例的有用默认值,python,class,Python,Class,我有一个表示接口的抽象基类。该类的子类作为属性存储在该类的其他子类中 例如: class AbstractBase(object): pass class Child(AbstractBase): def __init__(self, cls1, cls2): assert isinstance(cls1, AbstractBase) assert isinstance(cls2, AbstractBase) # just to show the
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
层次结构的深度和布局不能预先知道,但不会递归
我可以在AbstractBase
上放置哪些内容作为\uuuu repr\uuuu
,以便以有用的方式查看每个子类的属性
我目前的做法是:
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})
对于基类(没有属于AbstractBase
子类的属性),这将输出可读的内容,例如:
MyClass
{'var1': 1,
'var2': 2}
但是,对于具有AbstractBase
子类的类,它会中断,因为很难判断父类从何处开始,而另一个父类从何处结束(因为上面的\uuu repr\uuuu
并没有给出进一步的嵌套级别)
我很高兴看到下面这样的东西,想象cls1
和cls2
有一个int属性var
:
Child
{'cls1': {
'var': 1,
},
'cls2': {
'var': 0,
}
}
遗憾的是,我不知道如何做到这一点(或者这是否可能)。有什么想法吗?我喜欢这样做:
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
这是John Zwinck提议的一个稍加修改的版本 它考虑如何设置序列的格式,并稍微更改了格式。不过,目前它并不完美——我特别认为,对于字典来说,它会中断,因为iterable组件只会打印密钥
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
您需要类似于
def\uu repr\uuu(self,indent=1)
的东西,尽管可能没有办法将其与pformat
结合起来,所以您必须推出自己的一个,并且会出现一些您无法解决的奇怪情况。我喜欢这个响应。我稍微修改了它,以考虑序列,并打印(我认为是这样的)更具可读性的输出-请参阅我的答案。如果没有其他人有任何出色表现,我将在几天后接受您:)