属性是否应该进行重要的初始化?

时间:2009-09-06 17:35:27

标签: python properties initialization

我有一个对象,它基本上是Oracle序列的Python实现。由于各种原因,我们必须获取Oracle序列的nextval,在确定主键时手动计数,然后在插入记录后更新序列。

所以这是我的对象所做的步骤:

  1. 构造一个对象,其key_generator属性最初设置为无。
  2. 从数据库中获取第一个值,并将其传递给itertools.count。
  3. 使用属性next_key从该生成器返回密钥。
  4. 我有点不确定在哪里做第2步。我可以想到三种可能性:

    1. 跳过步骤1并在构造函数中执行第2步。我觉得这很邪恶,因为我倾向于不喜欢在构造函数中进行这种初始化。
    2. Make next_key在第一次调用时从数据库中获取起始键。我觉得这很邪恶,因为通常认为属性是微不足道的。
    3. next_key转换为get_next_key方法。我不喜欢这个,因为这里的属性看起来更自然。
    4. 3邪恶中哪一个较小?我倾向于#2,因为只有第一次调用此属性才会导致数据库查询。

3 个答案:

答案 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属性。