将 len() 和 sum() 作为变量存储在 python 中的约定

Convention for storing len() and sum() as variable in python

是否有关于何时以及如何将 len()sum() 的值存储到 python 中的约定?举个例子,如果你有一个 Class

class MyClass:

    def __init__(self, single_number = 4, multiple_numbers = [1,2,3]):
        self.single= single_number 
        self.multiple = multiple_numbers

    def info(self):
        print(f"The length of multiple is {len(self.multiple)}")
        print(f"The length of multiple is {len(self.multiple)*4}")
        print(f"The length of multiple is longer than {len(self.multiple)-1}")

if __name__ == "__main__":
    test=MyClass()
    test.info()
    # other stuff
    test.info()

你会在什么时候开始将 len(self.multiple) 存储为它自己的值?值得庆幸的是,python 不使用 len 来完成某些任务,例如 for my_numbers in multiple_numbers:,所以我不需要它只是为了迭代。此外,len 的值对于 class 的实例是静态的,并且在运行时的不同部分将(可能)多次需要,因此它不是临时变量 like here.一般来说,这似乎是(非常少量的)内存与计算之间的权衡。同样的问题适用于 sum().

这些问题的一部分是基于意见的,我很高兴听到你的想法,但我主要是在寻找一个关于这个的约定。

  1. 在什么情况下,len(self.multiple) 应该存储为它自己的值?
  2. 名称有约定吗? length_of_multiple_numbers 看似臃肿,但具有描述性。

我会使用局部变量,更多的是代码可读性而不是速度:

def info(self):
    n = len(self.multiple)
    print(f"The length of multiple is {n}")
    print(f"The length of multiple is {n*4}")
    print(f"The length of multiple is longer than {n-1}")

局部变量名可以很短,因为赋值和使用在同一个屏幕上。我使用自己的约定,但它们通常遵循常见的非正式约定。

我不会尝试将 len(...) 分配给 self 属性,更不用说全局了。

基本上任何在 function/method 中重复使用的值都是局部变量赋值的候选值。

我不相信有很多理由证明存储是合理的,除非每次的计算成本都很高。查看 hpaulj 的回答。

但是,如果您真的想要,可以使用 属性 甚至 可能 缓存它。

class MyList(list):

   @property
   def len_(self):
      return len(self)  #it's a list
or

   _len_ = None

   @property 
   def len_(self):
      if self._len_ is None:
          self._len_ = len(self)
      return self._len_

    def append(self, value):
       self._len_ = None
       super(MyList, self).append(value)

    ...and all other len-modifying methods also need to clear the cache.

同样,如果缓存它,则需要确保每次结果发生变化时都重置缓存。这也是您在实例变量上存储的想法的弱点 - 确保您没有过时数据的额外复杂性可能只有在您发现这确实是性能瓶颈后才应该被接受。

(在您的示例中使用 mutable default argument 作为 multiple_numbers 对这些问题没有帮助,顺便说一句)。通常扩展它 - 如果您的 sum/len 取决于可变项的状态,那么 storing/caching 计算是一个更糟糕的主意。即,如果 MyList 引用的对象本身具有需要聚合的 len/sum,则 MyList 没有任何业务 caching/storing.

命名方面,我可能会选择 名称,即添加 _cls -> cls_list -> list_.