简体   繁体   English

理解python中的阶乘函数

[英]Understanding a factorial function in python

I'm trying to understand if the following Python function: 我试图了解以下Python函数:

def factorial(i):
    if not hasattr(factorial, 'lstFactorial'):
        factorial.lstFactorial = [None] * 1000
    if factorial.lstFactorial[i] is None:
        iProduct = 1
        for iFactor in xrange(1, i+1):
            iProduct *= iFactor
        factorial.lstFactorial[i] = iProduct
    return factorial.lstFactorial[i]

would produce the same results as the equivalent in C#: 将产生与C#中的等效结果相同的结果:

long factorial(long n) 
{ 
   return n <= 1 ? 1 : n * factorial(n-1);
}

for a value of 12 or less. 值为12或更小。

I know nothing about Python but have just converted some Python code to C#. 我对Python一无所知,但刚刚将一些Python代码转换为C#。 This was the only function that I didn't fully understand. 这是我唯一没有完全理解的功能。

here is main algorithm 这是主要的算法

iProduct = 1
for iFactor in xrange(1, i+1):
    iProduct *= iFactor

other code is for caching results. 其他代码用于缓存结果。

Even without knowing Python, it must be clear to you that the two functions are far from identical. 即使不了解Python,也必须清楚这两个函数远非相同。 The C# version is calculating the factorial via recursion, whereas the Python one is doing it via iteration (although in a slightly weird way, with some odd memoization/caching going on - I guess in case you want to calculate multiple factorials in the lifetime of a program). C#版本通过递归计算阶乘,而Python则通过迭代计算它(虽然以一种奇怪的方式,一些奇怪的记忆/缓存继续进行 - 我想如果你想在生命周期中计算多个阶乘一个程序)。

Anyway, since calculating a factorial is a very simple algorithm, it works out the same in both cases. 无论如何,由于计算阶乘是一种非常简单的算法,因此在两种情况下都能得到相同的算法。

IANAPG (Python Guru), but it looks to me like the function is creating a static array of 1000 entries, then filling them on an as-needed basis to prevent recalculation. IANAPG(Python Guru),但在我看来,该函数正在创建一个包含1000个条目的静态数组,然后根据需要填充它们以防止重新计算。 In C++, it'd be something like: 在C ++中,它类似于:

long factorial(int i){
    //Cache array
    static long factorials[1000];
    if (!factorials[i]){ //If not cached, calculate & store
        int product = 1;
        for (int idx = 1; idx <= i + 1; ++idx){
            product *= idx;
        }
        factorials[i] = product;
    }
    return factorials[i]; //Return cached value
}

它将返回相同的结果,但Python版本可能会有更好的性能,因为它会记住结果

It just attaches an attribute called lstFactorial to factorial . 它只是将一个名为lstFactorial的属性lstFactorialfactorial This attribute is a list of 1000 values used to cache the results of previous calls. 此属性是用于缓存先前调用结果的1000个值的列表。

def factorial(i):
    if not hasattr(factorial, 'lstFactorial'): #program checks whether caching list exists
        factorial.lstFactorial = [None] * 1000 #if so, it creates a list of thousand None elements (it is more or less equivalent to C/C++'s NULL
    if factorial.lstFactorial[i] is None: #prog checks if that factorial has been already calculated
        iProduct = 1 #set result to 1
        for iFactor in xrange(1, i+1): # C's for(iFactor = 1; iFactor &lt;= i+1; iFactor++)
            iProduct *= iFactor #we multiply result times current loop counter
        factorial.lstFactorial[i] = iProduct #and put result in caching list
    return factorial.lstFactorial[i] #after all, we return the result, calculated jest now or obtained from cache

To be honest, it is not the best algorithm, since it uses cache only partially. 说实话,它不是最好的算法,因为它只部分使用缓存。

The simple, user-friendly factorial function (no caching) would be: 简单,用户友好的阶乘函数(无缓存)将是:

def factorial(i):
    if i == 0 or i == 1:
        return 1
    return i*factorial(i-1)

Of for lazy python programmers, most similiar to that C# example: 对于懒惰的python程序员,最类似于C#示例:

f = lambda i: i and i*f(i-1) or 1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM