如何实现一个函数来覆盖单个值和多个值

发布于 2024-07-14 08:39:26 字数 291 浏览 9 评论 0原文

假设您有一个像这样的值:

n = 5

和一个返回它的阶乘的函数,如下所示:

factorial(5)

如何处理多个值:

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

因此它以列表形式返回所有这些值的阶乘?

在不编写 2 个方法的情况下,处理这个问题最干净的方法是什么? Python 有没有好的方法来处理这种情况?

Say you have a value like this:

n = 5

and a function that returns the factorial of it, like so:

factorial(5)

How do you handle multiple values:

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

so it returns the factorials of all these values as a list?

What's the cleanest way to handle this, without writing 2 methods? Does Python have a good way to handle these kinds of situations?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

扮仙女 2024-07-21 08:39:26
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)
def Factorial(arg):
    try:
        it = iter(arg)
    except TypeError:
        pass
    else:
        return [Factorial(x) for x in it]
    return math.factorial(arg)

If it's iterable, apply recursivly. Otherwise, proceed normally.

Alternatively, you could move the last return into the except block.

If you are sure the body of Factorial will never raise TypeError, it could be simplified to:

def Factorial(arg):
    try:
        return [Factorial(x) for x in arg]
    except TypeError:
        return math.factorial(arg)
花想c 2024-07-21 08:39:26

列表理解

[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的答案更好,投票给那个答案。 干杯。

List comprehension:

[fac(n) for n in nums]

EDIT:

Sorry, I misunderstood, you want a method that handles both sequences and single values? I can't imagine why you wouldn't do this with two methods.

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

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

The alternative would be to do some sort of type-checking, which is better avoided unless you have some terribly compelling reason to do so.

EDIT 2:

MizardX's answer is better, vote for that one. Cheers.

那支青花 2024-07-21 08:39:26

有时会这样做。

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

它提供了一个几乎神奇的函数,可以处理简单的值和序列。

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

This is done sometimes.

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

It gives an almost magical function that works with simple values as well as sequences.

>>> factorial(5)
[120]
>>> factorial( 5, 6, 7 )
[120, 720, 5040]
>>> factorial( *[5, 6, 7] )
[120, 720, 5040]
半葬歌 2024-07-21 08:39:26

如果你问 Python 是否可以进行方法重载:不能。 因此,像这样执行多方法是一种相当不符合 Python 风格的定义方法的方式。 此外,命名约定通常是大写的类名和小写的函数/方法。

如果你想继续,最简单的方法就是创建一个分支:

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

或者,如果你感觉很奇特,你可以创建一个对任何函数执行此操作的装饰器:

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]]

If you're asking if Python can do method overloading: no. Hence, doing multi-methods like that is a rather un-Pythonic way of defining a method. Also, naming convention usually upper-cases class names, and lower-cases functions/methods.

If you want to go ahead anyway, simplest way would be to just make a branch:

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

Or, if you're feeling fancy, you could make a decorator that does this to any 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]

Although a more Pythonic way is to use variable argument lengths:

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]

Putting the two together into a deep mapping decorator:

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]]
一桥轻雨一伞开 2024-07-21 08:39:26

您可能想看看 NumPy/SciPy 的 向量化。

在 numpy 世界中,给定您的 single-int-arg Factorial 函数,
你会做类似的事情

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

,但请注意,最后一种情况返回单元素 numpy 数组而不是原始 int。

You might want to take a look at NumPy/SciPy's vectorize.

In the numpy world, given your single-int-arg Factorial function,
you'd do things like

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

although note that the last case returns a single-element numpy array rather than a raw int.

花伊自在美 2024-07-21 08:39:26

或者,如果您不喜欢列表理解语法,并且希望跳过新方法:

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]

Or if you don't like the list comprehension syntax, and wish to skip having a new method:

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]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文