Is it possible to display an objects instance variables in IPython like Matlab does?
我正试图从matlab转向python。而魔法呢?在ipython中,Matlab的一个非常好的特性是,您可以在命令行(通过省略;)上看到相关对象的实例变量(在Matlab中称为属性)。这在Python中是可能的吗(我猜是通过i python实现的)?
理想情况下是这样的一个类:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 |
将显示如下内容:
1 2 3 4 5 6 7 8 9 10 | mc = Myclass() mc <package.MyClass> <superclass1> <superclass2> Attributes: _x: 5 x: 105 Method Attributes: myFunction(self, y) |
号
是否可以通过重写类的print方法(如果存在这样的东西)来实现?或是通过伊普敦的魔法方法?
简短的答案是,在Python中无法获取对象所有属性的列表,因为这些属性可以动态生成。对于一个极端的例子,考虑这个类:好的。
1 2 3 4 5 6 7 | >>> class Spam(object): ... def __getattr__(self, attr): ... if attr.startswith('x'): ... return attr[1:] >>> spam = Spam() >>> spam.xeggs 'eggs' |
即使解释器能让人找出所有属性的列表,这个列表也是无限的。好的。
对于简单的类,
为了最大限度地提高"一切"的可读性,请使用
为了尽最大努力实现"一切"的程序化使用,请使用
这两种方法都可以处理
无论您使用什么,获取值和键都很容易。如果您使用的是
1 | {key: getattr(spam, key) for key in dir(spam)} |
号
最后一件事:"对象"是一个含糊不清的术语。它可以是"派生自
最后一件事是:你可能会注意到
所以,这很常见,你可能想把它写成一个函数:好的。
1 2 3 4 | 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%magic函数,或者从中生成一个%宏,或者将其保留为一个常规函数并显式调用它。好的。
在一条评论中,您询问是否可以将其打包成一个
如果您已经从一个根类继承了所有的类,那么这是一个好主意。您可以编写一个适用于所有类的单个
但是,要记住的一些事情:好的。
由于某种原因,python同时拥有
这只是惯例而不是规则,所以你可以随意打破它。但是,如果你打算打破它,你可能仍然想利用
更严重的是,您必须考虑
至于你想展示的具体内容:这很容易。像这样:好的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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 ' '.join(lines) |
正确地证明属性名是最困难的部分。(我可能搞错了,因为这是未经测试的代码…)其他的事情要么简单,要么有趣(对
通过实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | def get_public_variables(obj): from inspect import getmembers return [(name, value) for name, value in getmembers(obj, lambda x: not callable(x)) if not name.startswith('__')] class MySuperClass(object): def _repr_pretty_(self, p, cycle): for (name, value) in get_public_variables(self): f = '{:>12}{} {:<} ' line = f.format(str(name), ':', str(value)) # p.text(str(name) + ': ' + str(value) + ' ') p.text(line) class MyClass(MySuperClass): _x = 5 @property def x(self): return self._x + 100 |
给了我:
1 2 3 4 5 | mc = MyClass() mc Out[15]: _x: 5 x: 105 |
。
很明显,在空白等方面还需要进行一些微调,但这正是我试图完成的工作。
您可以使用
1 2 3 4 5 6 7 8 9 10 | class Dog: def __init__(self, name, age): self.name = name self.age = age d1 = Dog("Fido", 7) for key, val in d1.__dict__.items(): print(key,":", val) |
输出:
1 2 | age : 7 name : Fido |
号
但是,您可能会发现,对于可能具有大量实例变量和方法的实际对象,这并不适用。