繁体   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