Python __repr__ 和 None

发布于 2024-12-09 10:29:06 字数 336 浏览 0 评论 0原文

我对 Python 还很陌生,目前我需要一个 SqlAlchemy 类的 __repr__ 。 我有一个可以接受 Null 值的整数列,SqlAlchemy 将其转换为 None 。 例如:

class Stats(Base):
   __tablename__ = "stats"
   description = Column(String(2000))
   mystat = Column(Integer, nullable=True)

当 SqlAlchemy 返回 None 时,在 __repr__ 函数中表示“mystat”字段的正确方法是什么?

I'm quite new to Python and currently I need to have a __repr__ for a SqlAlchemy class.
I have an integer column that can accept Null value and SqlAlchemy converts it to None.
For example:

class Stats(Base):
   __tablename__ = "stats"
   description = Column(String(2000))
   mystat = Column(Integer, nullable=True)

What is the correct way to represent the "mystat" field in the __repr__ function when SqlAlchemy returns None?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

傲性难收 2024-12-16 10:29:06

__repr__ 应返回描述该对象的字符串。如果可能,它应该是一个计算结果为相等对象的有效 Python 表达式。对于 intstr 等内置类型来说也是如此:

>>> x = 'foo'
>>> eval(repr(x)) == x
True

如果不可能,它应该是 '<...>' 唯一描述对象的字符串。默认的 __repr__ 就是一个例子:

>>> class Foo(object):
        pass
>>>
>>> repr(Foo())
'<__main__.Foo object at 0x02A74E50>'

它使用对象在内存中的地址来唯一标识它。当然,地址并不能告诉我们太多有关该对象的信息,因此重写 __repr__ 并返回描述对象状态的字符串很有用。

对象的状态由它包含的其他对象定义,因此将它们的 repr 包含在您的状态中是有意义的。这正是 listdict 所做的:

>>> repr(['bar', Foo()])
"['bar', <__main__.Foo object at 0x02A74710>]"

在您的情况下,状态位于您的 Column 属性中,因此您想使用它们的 代表。您可以为此使用 %r 格式,它会插入参数的 repr()

def __repr__(self):
    return '<Stats: description=%r, mystat=%r>' % (self.description, self.mystat)

使用新格式的等效项:

def __repr__(self):
    return '<Stats: description={0.description!r}, mystat={0.mystat!r}>'.format(self)

The __repr__ should return a string that describes the object. If possible, it should be a valid Python expression that evaluates to an equal object. This is true for built-in types like int or str:

>>> x = 'foo'
>>> eval(repr(x)) == x
True

If that's not possible, it should be a '<...>' string uniquely describing the object. The default __repr__ is an example of this:

>>> class Foo(object):
        pass
>>>
>>> repr(Foo())
'<__main__.Foo object at 0x02A74E50>'

It uses the object's address in memory to uniquely identify it. Of course address doesn't tell us much about the object so it's useful to override __repr__ and return a string describing the object's state.

The object's state is defined by other objects it contains so it makes sense to include their repr in yours. This is exactly what list or dict do:

>>> repr(['bar', Foo()])
"['bar', <__main__.Foo object at 0x02A74710>]"

In your case, the state is in your Column properties so you want to use their repr. You can use the %r formatting for this, it inserts a repr() of the argument:

def __repr__(self):
    return '<Stats: description=%r, mystat=%r>' % (self.description, self.mystat)

An equivalent using the new formatting:

def __repr__(self):
    return '<Stats: description={0.description!r}, mystat={0.mystat!r}>'.format(self)
忆依然 2024-12-16 10:29:06

我试图找到一个可以在任何 SQLAlchemy 对象上使用的通用 __repr__ 方法,但只找到了这个页面。因此,我决定编写自己的代码,这就是我所做的:

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

if __debug__:
    # monkey-patch in useful repr() for all objects, but only in dev
    def tablerepr(self):
        return "<{}({})>".format(
            self.__class__.__name__,
            ', '.join(
                ["{}={}".format(k, repr(self.__dict__[k]))
                    for k in sorted(self.__dict__.keys())
                    if k[0] != '_']
            )
        )
    Base.__repr__ = tablerepr

这扩展了 Base 类以打印出特定实例的内容。因此,现在我创建的每个扩展 Base 的对象都将具有一个 __repr__ 方法,该方法不仅仅打印类名和实例哈希。

编辑:我添加了一个if __debug__,因为此更改可能会导致您可能不希望在生产环境中泄漏的信息泄漏。我还添加了一个sorted,以便显示保持一致。

I was trying to find a generic __repr__ method that could be used on any SQLAlchemy object and only found this page. So, I decided to write my own and here's what I've done:

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

if __debug__:
    # monkey-patch in useful repr() for all objects, but only in dev
    def tablerepr(self):
        return "<{}({})>".format(
            self.__class__.__name__,
            ', '.join(
                ["{}={}".format(k, repr(self.__dict__[k]))
                    for k in sorted(self.__dict__.keys())
                    if k[0] != '_']
            )
        )
    Base.__repr__ = tablerepr

This extends the Base class to print out the contents of the particular instance. So, now every object I create that extends the Base will have a __repr__ method that prints more than just the class name and the instance hash.

EDIT: I added an if __debug__ as this change may cause a leak of information you may not want leaked in a production environment. I also added a sorted so the display will be consistent.

神妖 2024-12-16 10:29:06

不是 sqlalchemy 的 generic_repr 装饰器-utils 提供适合您需求的基于社区的解决方案吗?

它将其保留为“无”。

Isn't the generic_repr decorator of sqlalchemy-utils providing a community based solution that suit your needs?

It leaves it as None.

ˉ厌 2024-12-16 10:29:06

也许 repr(mystat) 就是你想要的?

maybe repr(mystat) is what you want?

过去的过去 2024-12-16 10:29:06

如果 mystat 是 None else mystat,则为“Null”

'Null' if mystat is None else mystat

源来凯始玺欢你 2024-12-16 10:29:06

前面的答案显示了如何覆盖 Base.__repr__ 正是我所需要的。谢谢你!这里它是用 Python 3.7+ 的 f 字符串重写的,并覆盖了 Flask-sqlalchemy db.Model

def override_default_repr(self):
    class_name = self.__class__.__name__
    attribs = ", ".join(
        [
            f"{k}={self.__dict__[k]!r}"
            for k in sorted(self.__dict__.keys())
            if k[0] != "_"
        ]
    )
    return f"<{class_name}({attribs})>"

db.Model.__repr__ = override_default_repr

The previous answer showing how to override Base.__repr__ was exactly what I needed. Thank you! Here it is re-written with f-strings for Python 3.7+ and overriding the flask-sqlalchemy db.Model.

def override_default_repr(self):
    class_name = self.__class__.__name__
    attribs = ", ".join(
        [
            f"{k}={self.__dict__[k]!r}"
            for k in sorted(self.__dict__.keys())
            if k[0] != "_"
        ]
    )
    return f"<{class_name}({attribs})>"

db.Model.__repr__ = override_default_repr
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文