【问题标题】:How do I call a function twice or more times consecutively?如何连续调用函数两次或更多次?
【发布时间】:2012-02-21 07:25:31
【问题描述】:

在 Python 中是否有一种快捷方式可以连续调用函数两次或更多次?例如:

do()
do()
do()

也许像:

3*do()

【问题讨论】:

  • 请注意,3 * do() 是一个有效的 Python 表达式,其结果非常明确:它确实将调用 do 的返回值乘以 3。但是,可以编写一个装饰器,使人们能够编写诸如 (3 * do)() 之类的东西 - 在stackoverflow.com/questions/8998997/product-of-two-functions/… 有一个答案的变体
  • 我来到这里是因为我想知道是否有类似于您建议的方法来执行此操作......但是,它可能不足以保证新的“函数调用乘数运算符”,考虑到使用它而不是 for 循环只能节省大约 17 次击键。
  • 3*do() 这样的编程语言中添加语法糖绝不是一件好事。以后会引起很多问题和问题,更别提在这个语境下有着完全不同的含义了。
  • 看到关于语法糖的不同意见总是很有趣。有些人不喜欢它,有些人接受它。我们得到了上面的 python 意见(无论如何都是来自一个声音).. 同时在 ruby​​ 中你有 2.times do {block} (不是试图提出“ruby 更好”的论点,只是注意到不同编码社区如何看待这一点的差异)

标签: python function shortcut sequential


【解决方案1】:

一个简单的for循环?

for i in range(3):
  do()

或者,如果您对结果感兴趣并想收集它们,那么您可以成为 1 班轮:

vals = [do() for _ in range(3)]

【讨论】:

  • for-loop 也可以是 1 行:for i in range(3): do()
  • @julio.alegria 在 Python 中,一个衬里被认为是不好的做法——风格指南明确建议不要这样做。
  • @Lattyware 我知道,我只是想表明 for 循环也可以具有 作为 1 班轮的好处
  • 为什么单行被认为是不好的做法?
  • @alwbtc 它们对读者来说不太清楚 - 这是 python 样式指南的主要考虑因素之一,而且以后更难添加。见python.org/dev/peps/pep-0008
【解决方案2】:

我愿意:

for _ in range(3):
    do()

_ 是您不关心其值的变量的约定。

你可能还会看到一些人写:

[do() for _ in range(3)]

然而,这会稍微贵一些,因为它会创建一个包含每次调用do() 的返回值的列表(即使它是None),然后丢弃结果列表。除非您正在使用返回值列表,否则我不建议使用它。

【讨论】:

  • 我认为使用列表推导来重复操作从来都不是一个好主意
  • 确实如此。我应该更明确一点,我实际上并没有推荐
  • 是的,List Comprehensions 旨在创建新列表,不应用于产生副作用。
  • 如果您对结果的聚合感兴趣,那么聚合函数中的生成器理解(例如 sum)可以很好地工作:sum(do() for _ in range(3))sum(1 for _ in range(3) if do() > 3) 用于条件计数等.
  • @flutefreak7 列表推导是功能性的,另一个是过程性的:名称为do 的方法应该是一个过程(副作用且没有返回值)。因此,不要为此使用列表推导。但是,如果它是一个函数,则首先将其命名为一个(使用描述其返回内容的名词,如果返回布尔值则使用形容词),然后使用列表推导式。
【解决方案3】:

您可以定义一个重复传递的函数 N 次的函数。

def repeat_fun(times, f):
    for i in range(times): f()

如果你想让它更加灵活,你甚至可以将参数传递给被重复的函数:

def repeat_fun(times, f, *args):
    for i in range(times): f(*args)

用法:

>>> def do():
...   print 'Doing'
... 
>>> def say(s):
...   print s
... 
>>> repeat_fun(3, do)
Doing
Doing
Doing
>>> repeat_fun(4, say, 'Hello!')
Hello!
Hello!
Hello!
Hello!

【讨论】:

    【解决方案4】:

    另外三种方法:

    (I) 我认为使用map 也可能是一种选择,但在某些情况下需要使用Nones 生成一个附加列表,并且总是需要一个参数列表:

    def do():
        print 'hello world'
    
    l=map(lambda x: do(), range(10))
    

    (II) itertools 包含可用于迭代其他函数的函数https://docs.python.org/2/library/itertools.html

    (III) 我认为到目前为止还没有提到使用函数列表(它实际上是最接近最初讨论的语法):

    it=[do]*10
    [f() for f in it]
    

    或作为一个班轮:

    [f() for f in [do]*10]
    

    【讨论】:

    • codegolf调用mtimes函数的方式d:[d()for x in"1"*m]
    【解决方案5】:

    这是一种不需要使用 for 循环或定义中间函数或 lambda 函数(也是单线)的方法。该方法结合了以下两种思路:

    将这些放在一起,我们得到:

    next(islice(iter(do, object()), 3, 3), None)
    

    (将object() 作为哨兵传递的想法来自this 接受的堆栈溢出答案。)

    这是从交互式提示中看到的样子:

    >>> def do():
    ...   print("called")
    ... 
    >>> next(itertools.islice(iter(do, object()), 3, 3), None)
    called
    called
    called
    

    【讨论】:

      【解决方案6】:

      我的两分钱:

      from itertools import repeat 
      
      list(repeat(f(), x))  # for pure f
      [f() for f in repeat(f, x)]  # for impure f
      

      【讨论】:

      • 您能否详细说明一下在这种情况下纯和不纯的区别?
      • 当然——假设你有一个“不纯”的函数,它只打印而不做其他事情:如果你想让它打印 x 次,你会使用第二种方法;第一个只会导致一次打印。另一方面,如果您有一个不执行任何副作用的纯函数,您可以使用任何一种方法,但第一种方法只会导致该函数的一个应用程序,这可能会便宜得多。
      • list(repeat(f(), x)) 不重复函数调用,而是重复函数结果(如“纯/不纯f”的解释中所述)。因此不是 OP 要求的(多次调用该函数)。
      • @rlat 是的,但是如果它总是给出相同的结果并且没有副作用,为什么还要多次调用它?
      【解决方案7】:

      您可以尝试如下所示的while循环;

      def do1():
          # Do something
      
      def do2(x):
          while x > 0:
              do1()
              x -= 1
      
      do2(5)
      

      因此调用 do1 函数 5 次。

      【讨论】:

        【解决方案8】:
        from itertools import repeat, starmap
        
        results = list(starmap(do, repeat((), 3)))
        

        请参阅 itertools 模块中的 repeatfunc 配方,它实际上更强大。如果您只需要调用该方法但不关心返回值,您可以在 for 循环中使用它:

        for _ in starmap(do, repeat((), 3)): pass
        

        但这越来越难看。

        【讨论】:

          【解决方案9】:

          您可以使用itertools.repeatoperator.methodcaller 调用函数的__call__ 方法N 次。这是generator function 这样做的示例:

          from itertools import repeat
          from operator import methodcaller
          
          
          def call_n_times(function, n):
              yield from map(methodcaller('__call__'), repeat(function, n))
          

          使用示例:

          import random
          from functools import partial
          
          throw_dice = partial(random.randint, 1, 6)
          result = call_n_times(throw_dice, 10)
          print(list(result))
          # [6, 3, 1, 2, 4, 6, 4, 1, 4, 6]
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-04-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-04-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多