ipython matlab,有没有可能像Matlab那样在IPython中显示objects实例变量?

简而言之,在Python中无法获得对象所有属性的列表,因为这些属性可以动态生成。对于一个极端的例子,考虑这个类:>>> class Spam(object):

... def __getattr__(self, attr):

... if attr.startswith('x'):

... return attr[1:]

>>> spam = Spam()

>>> spam.xeggs

'eggs'

即使解释器能找出一个包含所有属性的列表,这个列表也是无限的。在

对于简单的类,spam.__dict__通常就足够了。它不处理动态属性、基于__slots__的属性、类属性、C扩展类、继承自上面大部分内容的属性以及其他各种东西。但这至少是某些东西,有时,它是你想要的东西。对于第一个近似值,它正是您在__init__或更高版本中显式分配的内容,而没有其他内容。在

为了达到“一切”的最佳效果,可以使用^{}。在

为了尽最大努力将“一切”用于编程,请使用^{}。(尽管实际上该实现只是cpython2.x中dir的包装器,但它在cpython3.2+中可以做得更多,事实上也可以做得更多。)

它们都将处理__dict__不能处理的大量内容,并且可能会跳过__dict__中您不想看到的内容。但它们本质上还是不完整的。在

无论使用什么方法,获取值和键都很容易。如果您使用的是__dict__或getmembers,那么这很简单;__dict__通常是dict,或者是与dict非常接近的东西,getmembers显式返回键值对。如果您正在使用dir,您可以很容易地得到一个dict:

^{pr2}$

最后一件事:“object”是一个有点模棱两可的术语。它可以表示“从object派生的类的任何实例”、“类的任何实例”、“新样式类的任何实例”或“任何类型的任何值”(模块、类、函数等)。您可以在任何事情上使用dir和getmembers;文档中详细描述了这一点。在

还有最后一件事:您可能会注意到getmembers返回了('__str__', )之类的内容,而您可能对此并不感兴趣。由于结果只是名称-值对,如果您只想删除__dunder__方法、_private变量等,这很简单。但通常,你需要过滤“成员种类”。getmembers函数接受一个过滤器参数,但是文档没有很好地解释如何使用它(而且,除此之外,希望您理解描述符的工作原理)。基本上,如果你想要一个过滤器,它通常是callable,lambda x: not callable(x),或者由inspect.isfoo函数组合而成的lambda。在

所以,这是很常见的,你可以把它写成一个函数:def get_public_variables(obj):

return [(name, value) for name, value

in inspect.getmembers(obj, lambda x: not callable(x))

if not name.startswith('_')]

你可以把它变成一个自定义的IPython%魔术函数,或者只是用它做一个%宏,或者把它作为一个常规函数显式调用。在

在一篇评论中,您问您是否可以将它打包成一个__repr__函数,而不是尝试创建一个%magic函数之类的。在

如果您已经从一个根类继承了所有类,这是一个好主意。您可以编写一个对所有类都有效的__repr__(或者,如果它适用于99%的类,那么您可以重写其他1%中的__repr__),然后每次在解释器中计算任何对象或将其打印出来时,都会得到您想要的结果。在

不过,有几点要记住:

Python既有__str__(如果你print一个对象,你会得到什么)和__repr__(如果你只是在交互提示下计算一个对象,你会得到什么)。通常,前者是一个很好的人类可读的表示,而后一个要么是eval-可(或可在交互提示中键入),要么是简洁的尖括号形式,它只给你足够的区分对象的类型和标识。在

那只是个惯例而不是一条规则,所以你可以随意打破它。但是,如果您要打破它,您可能仍然需要使用str/repr的区别,例如,使repr提供所有内部构件的完整转储,而str只显示有用的公共值。在

更严重的是,您必须考虑repr值是如何组成的。例如,如果您print或repralist,那么您实际上得到'[' + ', '.join(map(repr, item))) + ']'。如果使用多行repr,这看起来会很奇怪。如果你使用任何一种漂亮的打印机来缩进嵌套的集合,就像IPython内置的那样,情况会更糟。结果可能不会是不可读的,它只会打败漂亮的打印机提供的好处。在

至于你想展示的具体内容:这很简单。像这样:def __repr__(self):

lines = []

classes = inspect.getmro(type(self))

lines.append(' '.join(repr(cls) for cls in classes))

lines.append('')

lines.append('Attributes:')

attributes = inspect.getmembers(self, callable)

longest = max(len(name) for name, value in attributes)

fmt = '{:>%s}: {}' % (longest, )

for name, value in attributes:

if not name.startswith('__'):

lines.append(fmt.format(name, value))

lines.append('')

lines.append('Methods:')

methods = inspect.getmembers(self, negate(callable))

for name, value in methods:

if not name.startswith('__'):

lines.append(name)

return '\n'.join(lines)

正确地证明属性名是这里最难的部分。(我可能搞错了,因为这是未经测试的代码……)其他的事情要么简单,要么有趣(用不同的过滤器来getmembers看看它们做了什么)。在

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值