SQLAlchemy ORM教程中为何在__repr__值周围加上尖括号?
这个SQLAlchemy ORM教程使用了这个类:
>>> from sqlalchemy import Column, Integer, String
>>> class User(Base):
... __tablename__ = 'users'
...
... id = Column(Integer, primary_key=True)
... name = Column(String)
... fullname = Column(String)
... password = Column(String)
...
... def __init__(self, name, fullname, password):
... self.name = name
... self.fullname = fullname
... self.password = password
...
... def __repr__(self):
... return "<User('%s','%s', '%s')>" % (self.name, self.fullname, self.password)
为什么要费这么大劲去写一个在用eval()
执行时能正常工作的字符串,却又用尖括号把它包起来,导致这个功能失效呢?
我知道eval(repr(foo))
这个用法并不是__repr__
的唯一目的,但在这里故意让它失效似乎还是有点奇怪。难道我漏掉了什么更深层的逻辑,还是说这只是个随意的决定?
3 个回答
使用尖括号的一个理由和语义有关。虽然 eval(repr(2)) 总是等于 2
,但是 eval(repr(23094823589710L)) 却不等于 23094823589710L
,而且我认为 eval(repr(myinstance)) 一般情况下不会等于 instance
,特别是对于 mapper
类的实例来说。身份和相等性是否能这样支持,可能还要看类是否有唯一约束或其他特性。
另一个问题是类在命名空间中的可用性。如果某个类恰好不在作用域内,eval(repr(x))
就会引发 NameError
错误。
再举个复杂的例子:我写了一个自己的库函数(一个元类),它接受一个表名作为字符串,使用 type
动态创建一个类,并且 mapper
已经提供了 __init__
、__str__
和 __repr__
方法,然后返回这个新类。所有这些类的 __name__
属性都是相同的,因此在我的库函数中,无法支持 eval(repr(x)) is x
或者 eval(repr(x)) == x
。所以我在这些类中使用尖括号来表示 repr
。
我猜,出于这些原因,可能还有其他原因,文档中使用尖括号是为了避免让人产生 eval(repr(x)) is x
总是能被支持的期望。
尖括号的用法是Python解释器本身就采用的,所以这个问题更适合问问...GVR?
>>> class Foo(object):
... pass
...
>>> f = Foo()
>>> print repr(f)
<__main__.Foo object at 0x1004ab290>
要记住,eval
这个东西其实用得不多;为了它去拼接字符串(或者检查这些字符串是否真的能用)其实是多此一举,没必要费那么大劲。
直接把尖括号加上去要简单得多,而且也不会让人想到去用 eval
(如果不小心的话,这个东西是挺危险的)。
换句话说,这里并不是故意要让 eval(repr(x))
出问题。其实在 __repr__
的输出周围加上尖括号是个习惯而已。