是否可以像 Matlab 一样在 IPython 中显示对象实例变量?

2024-01-10

我正在尝试从 Matlab 转向 Python。而魔法? IPython 很好,Matlab 的一个非常好的功能是您可以在命令行上(通过省略 ;)看到相关对象的实例变量(在 Matlab 中称为属性)。这在 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

会显示类似以下内容:

mc = Myclass()
mc
<package.MyClass> <superclass1> <superclass2>

Attributes:
_x: 5
 x: 105

Method Attributes:
myFunction(self, y)

是否可以覆盖类的 print 方法(如果存在这样的方法)?或者通过Python中的魔术方法?


简而言之,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__或稍后,仅此而已。

为了尽最大努力实现以人类可读性为目标的“一切”,请使用dir(spam) http://docs.python.org/2/library/functions.html#dir.

为了尽最大努力针对“一切”进行编程使用,请使用inspect.getmembers(spam) http://docs.python.org/2/library/inspect.html#inspect.getmembers。 (尽管实际上实现只是一个包装dir在 CPython 2.x 中,它could做得更多——事实上在 CPython 3.2+ 中也是如此。)

这些都可以处理各种各样的事情__dict__不能,并且可能会跳过__dict__但你不想看到。但它们本质上仍然是不完整的。

无论您使用什么,获取值和键都很容易。如果您正在使用__dict__ or getmembers,这是微不足道的;这__dict__通常是dict,或者行为足够接近的东西dict为了您的目的,并且getmembers显式返回键值对。如果您正在使用dir,你可以得到一个dict非常简单地:

{key: getattr(spam, key) for key in dir(spam)}

最后一件事:“对象”是一个有点含糊的术语。它可以意味着“派生自的类的任何实例object”、“类的任何实例”、“新式类的任何实例”或“任何类型的任何值”(模块、类、函数等)。您可以使用dir and getmembers几乎任何事情;文档中描述了这意味着什么的确切细节。

最后一件事:你可能会注意到getmembers返回类似的东西('__str__', <method-wrapper '__str__' of Spam object at 0x1066be790>),您可能对此不感兴趣。由于结果只是名称-值对,如果您只想删除__dunder__方法,_private变量等等,这很简单。但通常,您想要过滤“成员类型”。这getmembers函数接受一个过滤器参数,但文档并没有很好地解释如何使用它(最重要的是,期望您了解描述符的工作原理)。基本上,如果你想要一个过滤器,通常是callable, lambda x: not callable(x), or a lambda由以下组合组成inspect.isfoo功能。

因此,这很常见,您可能想将其编写为函数:

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 函数,或者仅使用它创建一个 % 宏,或者将其保留为常规函数并显式调用它。


在评论中,您询问是否可以将其打包成一个__repr__函数而不是尝试创建 %magic 函数或其他函数。

如果您已经让所有类都继承自单个根类,那么这是一个好主意。可以单独写一个__repr__适用于您的所有课程(或者,如果它适用于 99% 的课程,您可以覆盖它__repr__在另外 1% 中),然后每次你在解释器中评估任何对象或打印它们时,你都会得到你想要的。

但是,需要记住以下几点:

Python 两者都有__str__(如果你得到什么print一个物体)和__repr__(如果你只是在交互式提示下评估一个对象,你会得到什么)是有原因的。通常,前者是一个很好的人类可读的表示,而后者是eval-able(或可在交互式提示中输入),或者简洁的尖括号形式,足以让您区分对象的类型和身份。

这只是一个惯例而不是规则,所以你可以随意打破它。但是,如果您are要打破它,你可能仍然想利用str/repr区别——例如,使repr为您提供所有内部结构的完整转储,同时str仅显示有用的公共价值观。

更严重的是,你必须考虑如何repr值是组成的。例如,如果您print or repr a list,你有效地得到,'[' + ', '.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看看他们做了什么)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否可以像 Matlab 一样在 IPython 中显示对象实例变量? 的相关文章

  • 在 SQLAlchemy 中,过滤器是在连接之前还是之后应用?

    使用 SQLAlchemy 我执行如下查询 import models as m import sqlalchemy as sa s session maker q s query m ShareCount m Article join m
  • 有什么好的适用于 Google App Engine 应用程序的 AJAX 框架吗? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在尝试在我的 Google App Engine 应用程序中实现 AJAX 因此我正在寻找一个好的
  • 在 Python 中延迟转置列表

    所以 我有一个延迟生成的可迭代的三元组 我试图弄清楚如何将其转换为 3 个可迭代对象 分别由元组的第一个 第二个和第三个元素组成 然而 我希望这件事能懒惰地完成 所以 举例来说 我希望 1 2 3 4 5 6 7 8 9 将变成 1 4 7
  • 在 MATLAB 中使用 FFT 的频率响应

    这是场景 使用频谱分析仪 我有输入值和输出值 样本数是32000采样率为2000样本 秒 输入是正弦波50 hz 输入为电流 输出为压力 单位 psi 我如何使用 MATLAB 根据这些数据计算频率响应 使用 MATLAB 中的 FFT 函
  • 为什么我会收到 ValueError:系列的真值不明确。使用 a.empty、a.bool()、a.item()、a.any() 或 a.all()

    以下代码给出了值错误 major males for row in recent grads if recent grads Men gt recent grads Women major males append recent grads
  • pandas 数据框的最大大小

    我正在尝试使用读取一个有点大的数据集pandas read csv or read stata功能 但我不断遇到Memory Errors 数据帧的最大大小是多少 我的理解是 只要数据适合内存 数据帧就应该没问题 这对我来说不应该是问题 还
  • 对法语文本进行词形还原[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有一些法语文本需要以某种方式进行处理 为此 我需要 首先 将文本标记为单词 然后对这些单词进行词形还原以避免多次处理相同的词根 据我
  • Python 中“is”运算符的语义是什么?

    如何is运算符确定两个对象是否相同 它是如何工作的 我找不到它的记录 来自文档 http docs python org reference datamodel html 每个对象都有一个身份 一个类型 和一个值 对象的身份 一旦发生就永远
  • 如何在Python中手动对数字列表进行排序?

    规格 Ubuntu 13 04 Python 3 3 1 背景 Python的初学者 遇到了这个 手动排序 问题 我被要求做的事情 让用户输入 3 个数值并将它们存储在 3 个不同的变量中 不使用列表或排序算法 手动将这 3 个数字从小到大
  • argparse 不检查位置参数

    我正在创建一个脚本 它使用 argparse 接受位置参数和可选参数 我已经阅读了 Doug 的教程和 python 文档 但找不到答案 parser argparse ArgumentParser description script t
  • 右键单击 QPushButton 上的 contextMenu

    对于我的应用程序 我在 Qt Designer 中创建了一个 GUI 并将其转换为 python 2 6 代码 关于一些QPushButton 与设计器创建 我想添加右键单击上下文菜单 菜单选项取决于应用程序状态 如何实现这样的上下文菜单
  • 使用 python 从 CSV 创建字典

    我有一个 CSV 格式的文件 其中 A B 和 C 是标题 我如何以Python方式将此CSV转换为以下形式的字典 A 1 B 4 C 7 A 2 B 5 C 8 A 3 B 6 C 9 到目前为止我正在尝试以下代码 import csv
  • 当元组列表中相同项目的值是字符串时,对它们的值求和

    如果我有这样的元组列表 my list books 5 books 10 ink 20 paper 15 paper 20 paper 15 我怎样才能把列表变成这样 books 15 ink 20 paper 50 即添加同一项目的费用
  • 如何在 python 中使用交叉验证执行 GridSearchCV

    我正在执行超参数调整RandomForest如下使用GridSearchCV X np array df features all features y np array df gold standard labels x train x
  • matplotlib vlines 图中未应用 y 轴的最小值

    我正在 matplotlib 中绘制 vlines 图 数据集中的所有 y 值如下 gt 0 我希望 y 轴最底部的刻度能够读取0 但相反 我得到 500 这是代码 usr bin env python import numpy as np
  • 类变量:“类列表”与“类布尔值”[重复]

    这个问题在这里已经有答案了 我不明白以下示例的区别 一次类的实例可以更改另一个实例的类变量 而另一次则不能 示例1 class MyClass object mylist def add self self mylist append 1
  • Pygame:有人可以帮我实现双跳吗?

    我知道已经有其他关于此问题的帖子了 但我的运动系统与我发现的有点不同 所以随后我问这个问题 我的运动系统基于一个名为的命名元组Move up left right down 然后就是这个 def update self move block
  • 解析整数集的字符串并列出间隔

    I have 2 5 7 9 12 string 我想从中获取 2 5 7 8 9 12 列表 python中有没有内置的函数 Thanks UPD 我想 直接的答案是No 不管怎样 谢谢你的 片段 使用一个 建议者斯文 马尔纳克 s 2
  • 如何将Python包从旧版本安装到新版本?

    我正在使用 python 3 7 最近在 Linux 中安装了 python 3 8 是否有任何 bash 命令或脚本可以获取 3 7 的所有软件包列表并在 3 8 版本中一一安装 我想避免每个包裹都手工完成 注意 我将它们安装在我的系统中
  • 如何使 Django 自定义管理命令参数不再需要?

    我正在尝试在 django 中编写自定义管理命令 如下所示 class Command BaseCommand def add arguments self parser parser add argument delay type int

随机推荐