_repr_html_ 自定义 __getattr__ 实现时不显示

问题描述 投票:0回答:1

我正在尝试在 python 类上实现

_repr_html_
(docs)。

该类是一个只读外观,用于使用属性表示法导航类似 JSON 的对象(基于 Fluent Python、Rahmalho (O'Reilly) 的示例 19-5)。它有一个自定义的

__getatrr__
方法来实现此行为:

from collections import abc


class FrozenJSON:

    def __init__(self, mapping):
        self._data = dict(mapping)

    def __repr__(self):
        return "FrozenJSON({})".format(repr(self._data))

    def _repr_html_(self):
        return (
            "<ul>"
            + "\n".join(
                f"<li><strong>{k}:</strong> {v}</li>"
                for k, v in self._data.items()
            )
            + "</ul>"
        )

    def __getattr__(self, name):
        if hasattr(self._data, name):
            return getattr(self._data, name)
        else:
            return FrozenJSON.build(self._data[name])

    @classmethod
    def build(cls, obj):
        if isinstance(obj, abc.Mapping):
            return cls(obj)
        elif isinstance(obj, abc.MutableSequence):
            return [cls.build(item) for item in obj]
        else:
            return obj

    def __dir__(self):
        return list(self._data.keys())

班级的行为如下:

>>> record = FrozenJSON({"name": "waldo", "age": 32, "occupation": "lost"})
>>> record.occupation
'lost'

但是

_repr_html_
在 IPython 环境中不会显示(我尝试过 vscode 和 jupyter lab)。

注释掉

__getattr__
方法会导致显示 HTML 表示形式,因此我相当有信心问题与此有关。

_repr_html_
其他对象在我的环境中工作正常(例如 pandas DataFrames)。)

以下内容没有帮助:

    def __getattr__(self, name):
        if hasattr(self._data, name):
            return getattr(self._data, name)
        elif name == "_repr_html_":
            return self._repr_html_
        else:
            return FrozenJSON.build(self._data[name])

我不太了解 vscode / juptyer 实验室如何知道调用

_repr_html_
而不是
__repr__
,以及这个
__getattr__
如何打破这一点。

预先感谢您的帮助!

python visual-studio-code ipython getattr repr
1个回答
0
投票

IPython 检查不存在的属性是否会为类引发

AttributeError
。如果发生这种情况,显然一切都好并且使用
_repr_html_
。如果没有为不存在的属性引发
AttributeError
,则使用
__repr__

(可以通过在

name
内打印
__getattr__
来找出是什么属性;它被称为
_ipython_canary_method_should_not_exist_
。)

我(还)不知道 IPython 到底是如何做到这一点的,更重要的是,为什么这样做。

在您的情况下,不存在的属性将引发

KeyError
,因为该行

            return FrozenJSON.build(self._data[name])

因此,请确保当未找到

__getattr__
时,
AttributeError
会引发实际的
name
,例如如下:

    def __getattr__(self, name):
        if hasattr(self._data, name):
            return getattr(self._data, name)
        else:
            try:
                return FrozenJSON.build(self._data[name])
            except KeyError:
                raise AttributeError('no such attribute')

现在 IPython 很高兴,你的 HTML 将显示在笔记本中。

© www.soinside.com 2019 - 2024. All rights reserved.