我有一个对象,它基本上是Oracle序列的Python实现。由于各种原因,我们必须获取Oracle序列的nextval,在确定主键时手动计数,然后在插入记录后更新序列。
所以这是我的对象所做的步骤:
key_generator
属性最初设置为无。next_key
从该生成器返回密钥。我有点不确定在哪里做第2步。我可以想到三种可能性:
next_key
在第一次调用时从数据库中获取起始键。我觉得这很邪恶,因为通常认为属性是微不足道的。next_key
转换为get_next_key
方法。我不喜欢这个,因为这里的属性看起来更自然。3邪恶中哪一个较小?我倾向于#2,因为只有第一次调用此属性才会导致数据库查询。
答案 0 :(得分:4)
我认为你的怀疑来自PEP-8:
Note 3: Avoid using properties for computationally expensive operations; the attribute notation makes the caller believe that access is (relatively) cheap.
遵守标准行为通常是个好主意;这将是废除解决方案#2的理由。
但是,如果你感觉接口在属性方面比方法更好,那么我只是记录第一次调用更昂贵,然后继续(解决方案#2)。 /> 最后,建议应该被解释。
答案 1 :(得分:2)
我同意属性访问和看起来像它的所有内容(即Python上下文中的属性)应该是相当简单的。如果属性将执行可能代价高昂的操作,请使用方法将其显式化。我建议使用像“fetch_XYZ”或“retrieve_XYZ”这样的名称,因为“get_XYZ”在某些语言(例如Java)中用作简单属性访问的约定,非常通用,并且听起来也不“昂贵”。
一个好的准则是:如果你的属性可能抛出一个不是由编程错误引起的异常,那么它应该是一种方法。例如,从属性中抛出(假设的)DatabaseConnectionError是不好的,而抛出ObjectStateError就没问题。
另外,当我理解正确时,只要访问了next_key属性,就要返回下一个键。我强烈反对在你的属性中产生副作用(除了缓存,廉价的懒惰初始化等)。属性(以及该问题的属性)应该是幂等的。
答案 2 :(得分:0)
我已经确定我提出的解决方案中的关键气味是我创建的属性中包含“next”这个词。因此,我决定将我的DatabaseIntrospector类转换为KeyCounter类并实现迭代器协议(即创建一个返回下一个键的普通旧的next方法),而不是生成next_key
属性。