簡體   English   中英

如何實現 function 以涵蓋單個值和多個值

[英]How to implement a function to cover both single and multiple values

假設您有這樣的值:

n = 5

和一個 function 返回它的階乘,如下所示:

factorial(5)

你如何處理多個值:

nums = [1,2,3,4,5]
factorial (nums)

所以它將所有這些值的階乘作為列表返回?

在不編寫 2 種方法的情況下,最干凈的處理方法是什么? Python有處理這類情況的好辦法嗎?

def Factorial(arg):
    try:
        it = iter(arg)
    except TypeError:
        pass
    else:
        return [Factorial(x) for x in it]
    return math.factorial(arg)

如果它是可迭代的,則遞歸應用。 否則,正常進行。

或者,您可以將最后一個return移動到except塊中。

如果您確定Factorial的主體永遠不會引發TypeError ,它可以簡化為:

def Factorial(arg):
    try:
        return [Factorial(x) for x in arg]
    except TypeError:
        return math.factorial(arg)

列表理解

[fac(n) for n in nums]

編輯:

抱歉,我誤會了,您想要一種同時處理序列和單個值的方法嗎? 我無法想象你為什么不使用兩種方法來做到這一點。

def factorial(n):
    # implement factorial here
    return answer

def factorial_list(nums):
    return [factorial(n) for n in nums]

另一種方法是進行某種類型檢查,除非你有一些非常令人信服的理由,否則最好避免這樣做。

編輯2:

MizardX 的答案更好,投票給那個。 干杯。

有時會這樣做。

def factorial( *args ):
    def fact( n ):
        if n == 0: return 1
        return n*fact(n-1)
    return [ fact(a) for a in args ]

它提供了一個幾乎神奇的 function,它適用於簡單的值和序列。

>>> factorial(5)
[120]
>>> factorial( 5, 6, 7 )
[120, 720, 5040]
>>> factorial( *[5, 6, 7] )
[120, 720, 5040]

如果您問 Python 是否可以進行方法重載:否。 因此,執行這樣的多方法是定義方法的一種相當非 Pythonic 的方式。 此外,命名約定通常大寫 class 名稱,小寫函數/方法。

如果你想 go 無論如何,最簡單的方法就是創建一個分支:

def Factorial(arg):
  if getattr(arg, '__iter__', False): # checks if arg is iterable
    return [Factorial(x) for x in arg]
  else:
    # ...

或者,如果您喜歡,您可以制作一個裝飾器,對任何 function 執行此操作:

def autoMap(f):
    def mapped(arg):
        if getattr(arg, '__iter__', False):
            return [mapped(x) for x in arg]
        else:
            return f(arg)
    return mapped

@autoMap
def fact(x):
    if x == 1 or x == 0:
        return 1
    else:
        return fact(x-1) + fact(x-2)

>>> fact(3)
3
>>> fact(4)
5
>>> fact(5)
8
>>> fact(6)
13
>>> fact([3,4,5,6])
[3, 5, 8, 13]

盡管更 Pythonic 的方式是使用可變參數長度:

def autoMap2(f):
    def mapped(*arg):
        if len(arg) != 1:
            return [f(x) for x in arg]
        else:
            return f(arg[0])
    return mapped

@autoMap2
def fact(n):
# ...

>>> fact(3,4,5,6)
[3, 5, 8, 13]

將兩者組合成一個深度映射裝飾器:

def autoDeepMap(f):
    def mapped(*args):
        if len(args) != 1:
            return [mapped(x) for x in args]
        elif getattr(args[0], '__iter__', False):
            return [mapped(x) for x in args[0]]
        else:
            return f(args[0])
    return mapped

@autoDeepMap
def fact(n):
# ...

>>> fact(0)
1
>>> fact(0,1,2,3,4,5,6)
[1, 1, 2, 3, 5, 8, 13]
>>> fact([0,1,2,3,4,5,6])
[1, 1, 2, 3, 5, 8, 13]
>>> fact([0,1,2],[3,4,5,6])
[[1, 1, 2], [3, 5, 8, 13]]
>>> fact([0,1,2],[3,(4,5),6])
[[1, 1, 2], [3, [5, 8], 13]]

或者,如果您不喜歡列表理解語法,並且希望跳過使用新方法:

def factorial(num):
    if num == 0:
        return 1
    elif num > 0:
        return num * factorial(num - 1)
    else:
        raise Exception("Negative num has no factorial.")

nums = [1, 2, 3, 4, 5]
# [1, 2, 3, 4, 5]

map(factorial, nums)
# [1, 2, 6, 24, 120, 720]

您可能想看看 NumPy/SciPy 的vectorize

在 numpy 世界中,給定你的單整數參數階乘 function,你會做類似的事情

  vFactorial=np.vectorize(Factorial)
  vFactorial([1,2,3,4,5])
  vFactorial(6)

盡管請注意,最后一種情況返回的是單元素 numpy 數組而不是原始 int。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM