Python中的__repr__和None
我刚开始学习Python,现在需要为一个SqlAlchemy类写一个__repr__
方法。这个类里有一个整数类型的字段,它可以接受Null
值,而SqlAlchemy会把这个值转换成None
。举个例子:
class Stats(Base):
__tablename__ = "stats"
description = Column(String(2000))
mystat = Column(Integer, nullable=True)
当SqlAlchemy返回None
时,应该如何在__repr__
方法中正确地表示“mystat”这个字段呢?
6 个回答
难道不是因为 sqlalchemy-utils 里的 generic_repr
装饰器提供了一个社区开发的解决方案,正好符合你的需求吗?
它的结果是 None。
我在找一个通用的 __repr__
方法,可以在任何 SQLAlchemy 对象上使用,结果只找到这一页。于是我决定自己写一个,下面是我做的:
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
,这样显示的内容会保持一致。
__repr__
方法应该返回一个描述对象的字符串。如果可能的话,这个字符串应该是一个有效的 Python 表达式,能够生成一个相同的对象。这对于像 int
或 str
这样的内置类型是成立的:
>>> x = 'foo'
>>> eval(repr(x)) == x
True
如果不能做到这一点,那么它应该是一个形如 '<...>'
的字符串,能够唯一地描述这个对象。默认的 __repr__
就是一个这样的例子:
>>> class Foo(object):
pass
>>>
>>> repr(Foo())
'<__main__.Foo object at 0x02A74E50>'
它使用对象在内存中的地址来唯一标识这个对象。当然,地址并不能告诉我们太多关于这个对象的信息,所以重写 __repr__
方法,返回一个描述对象状态的字符串是很有用的。
对象的状态是由它包含的其他对象定义的,因此在你的描述中包含它们的 repr
是有意义的。这正是 list
或 dict
所做的:
>>> repr(['bar', Foo()])
"['bar', <__main__.Foo object at 0x02A74710>]"
在你的情况下,状态在你的 Column
属性中,所以你想使用它们的 repr
。你可以使用 %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)