我正试图从Matlab转向Python。而魔法呢?在ipythonisnice中,Matlab的一个非常好的特性是,您可以在命令行上(通过省略;)看到相关对象的实例变量(在Matlab中称为properties)。在python中(我猜是通过IPython实现的)这可能吗?在
最好是这样的班级:
class MyClass(object):
_x = 5
@property
def x(self):
return self._x + 100
@x.setter
def x(self, value):
self._x = value + 1
def myFunction(self, y):
return self.x ** 2 + y
会显示如下内容:
^{pr2}$是否可以通过重写类的print方法(如果有这样的东西存在的话)?或者通过ipython的魔法方法?在
简而言之,在Python中无法获得对象所有属性的列表,因为这些属性可以动态生成。对于一个极端的例子,考虑这个类:
即使解释器能找出一个包含所有属性的列表,这个列表也是无限的。在
对于简单的类,
spam.__dict__
通常就足够了。它不处理动态属性、基于__slots__
的属性、类属性、C扩展类、继承自上面大部分内容的属性以及其他各种东西。但这至少是某些东西,有时,它是你想要的东西。对于第一个近似值,它正是您在__init__
或更高版本中显式分配的内容,而没有其他内容。在为了达到“一切”的最佳效果,可以使用^{} 。在
为了尽最大努力将“一切”用于编程,请使用^{} 。(尽管实际上该实现只是cpython2.x中
dir
的包装器,但它在cpython3.2+中可以做得更多,事实上也可以做得更多。)它们都将处理
__dict__
不能处理的大量内容,并且可能会跳过__dict__
中您不想看到的内容。但它们本质上还是不完整的。在无论使用什么方法,获取值和键都很容易。如果您使用的是
^{pr2}$__dict__
或getmembers
,那么这很简单;__dict__
通常是dict
,或者是与dict
非常接近的东西,getmembers
显式返回键值对。如果您正在使用dir
,您可以很容易地得到一个dict
:最后一件事:“object”是一个有点模棱两可的术语。它可以表示“从
object
派生的类的任何实例”、“类的任何实例”、“新样式类的任何实例”或“任何类型的任何值”(模块、类、函数等)。您可以在任何事情上使用dir
和getmembers
;文档中详细描述了这一点。在还有最后一件事:您可能会注意到
getmembers
返回了('__str__', <method-wrapper '__str__' of Spam object at 0x1066be790>
)之类的内容,而您可能对此并不感兴趣。由于结果只是名称-值对,如果您只想删除__dunder__
方法、_private
变量等,这很简单。但通常,你需要过滤“成员种类”。getmembers
函数接受一个过滤器参数,但是文档没有很好地解释如何使用它(而且,除此之外,希望您理解描述符的工作原理)。基本上,如果你想要一个过滤器,它通常是callable
,lambda x: not callable(x)
,或者由inspect.isfoo
函数组合而成的lambda
。在所以,这是很常见的,你可以把它写成一个函数:
你可以把它变成一个自定义的IPython%魔术函数,或者只是用它做一个%宏,或者把它作为一个常规函数显式调用。在
在一篇评论中,您问您是否可以将它打包成一个
__repr__
函数,而不是尝试创建一个%magic函数之类的。在如果您已经从一个根类继承了所有类,这是一个好主意。您可以编写一个对所有类都有效的
__repr__
(或者,如果它适用于99%的类,那么您可以重写其他1%中的__repr__
),然后每次在解释器中计算任何对象或将其打印出来时,都会得到您想要的结果。在不过,有几点要记住:
Python既有
__str__
(如果你print
一个对象,你会得到什么)和__repr__
(如果你只是在交互提示下计算一个对象,你会得到什么)。通常,前者是一个很好的人类可读的表示,而后一个要么是eval
-可(或可在交互提示中键入),要么是简洁的尖括号形式,它只给你足够的区分对象的类型和标识。在那只是个惯例而不是一条规则,所以你可以随意打破它。但是,如果您要打破它,您可能仍然需要使用
str
/repr
的区别,例如,使repr
提供所有内部构件的完整转储,而str
只显示有用的公共值。在更严重的是,您必须考虑
repr
值是如何组成的。例如,如果您print
或repr
alist
,那么您实际上得到'[' + ', '.join(map(repr, item))) + ']'
。如果使用多行repr
,这看起来会很奇怪。如果你使用任何一种漂亮的打印机来缩进嵌套的集合,就像IPython内置的那样,情况会更糟。结果可能不会是不可读的,它只会打败漂亮的打印机提供的好处。在至于你想展示的具体内容:这很简单。像这样:
正确地证明属性名是这里最难的部分。(我可能搞错了,因为这是未经测试的代码……)其他的事情要么简单,要么有趣(用不同的过滤器来
getmembers
看看它们做了什么)。在通过实现
_repr_pretty_
,我能够用IPython实现我想要的(至少大致上是这样):给我的答案是:
^{pr2}$很明显,在空白等方面还有一些微调要做,但这正是我试图完成的
您可以使用
obj.__dict__
获取对象的实例变量,例如:输出:
^{pr2}$但是,您可能会发现,对于可能具有大量实例变量和方法的实际对象,这种方法并不适用。在
相关问题 更多 >
编程相关推荐