最简单的方法是在python中重复一些东西

时间:2014-07-30 01:39:22

标签: python loops nested-loops repeat

假设您要编写一个程序,要求用户提供X编号并将其存储在A中,然后存储为Y编号并将其存储在B中

在你投票结束之前:是的,这个问题已经被问到herehereherehere以及可能在其他地方,但我回复了每一个问题。在这个问题中提出的解决方案解释了为什么它们不是我正在寻找的,所以如果您认为它是重复的,请在投票结束前继续阅读。这是一个严肃的问题,请参阅最后一段,了解支持我在这里尝试实现的功能的一小部分语言。

A = []
B = []

# First possibilty : using while loops
# you need to have a counter
i = 0
while (i < X):
    A.append(input())
    # and increment it yourself
    i+=1
# you need to reset it
i = 0
while (i < Y):
    B.append(input())
    # and increment it again
    i+=1

所以基本上你需要重复某个事情x次,然后再重复Y次,但是python只有while循环和for循环。 while循环不是重复N次的某个事情,而是在某个条件为True时重复某些事情,这就是为什么你必须使用一个计数器,初始化它,递增它并对它进行测试。

第二种解决方案是使用for循环:

# No need to create a counter
for x in xrange(x):
    A.append(input())
    # No need to increment the counter

# no need to reset the counter
for x in xrange(Y):
    B.append(input())

这是好多了:),但仍然有点令人讨厌:为什么我还需要提供“x”,当我不需要x?在我的代码中,我不需要知道我在什么循环迭代中,我只需要重复N次,所以为什么我必须创建一个计数器呢?有没有办法完全摆脱柜台?想象你可以写下这样的东西:

# No need to supply any variable !
repeat(x):
    A.append(input())

repeat(Y):
    B.append(input())

那不是更优雅吗?这不会更准确地反映您对代码的可能读者的意图吗?遗憾的是,python不够灵活,无法创建新的语言结构(更高级的语言允许这样做)。所以我仍然需要使用for或while循环。考虑到这一限制,我如何才能更接近上层代码?

这是我试过的

def repeat(limit):
    if hasattr(repeat,"counter"):
        repeat.counter += 1
        return repeat.counter < limit
    repeat.limit   = limit
    repeat.counters = 0
    return limit > 0 and True

while repeat(x):
    A.append(input())

while repeat(Y):
    B.append(input())

此解决方案适用于简单循环,但显然不适用于嵌套循环。

我的问题是

您是否知道任何其他可能的实现方式可以让我获得与repeat相同的界面?

建议解决方案的重建

建议的解决方案1.1:使用itertools.repeat

你必须将你的代码放在一个函数中,并以某种方式在itertools.repeat中调用该函数。它与上面的重复实现不同,你可以在任意缩进的代码块上使用它。

建议解决方案1.2:在for循环中使用itertools.repeat

import itertools

for _ in itertools.repeat(None, N):
    do_something()

你还在写一个for循环,而for循环需要一个变量(你提供_),这完全错过了这个点,再看看:

while repeat(5):
    do_x()
    do_y()
    do_z()

仅仅为了循环而没有提供任何东西。这就是我想要实现的目标。

建议的解决方案2:使用itertools.count

1)你走了一半。是的,你摆脱手动递增计数器,但你仍然需要手动创建一个计数器。示例:

c = itertools.count(1,1) # You still need this line
while( c.next() < 7):
    a = 1
    b = 4
    d = 59
    print "haha"
    # No need to increment anything, that's good.
    # c.incr() or whatever that would be

你还需要将计数器重置为0,如果你在它上面使用with语句,我认为这可能隐藏在函数内部,这样在with语句的每一端都会重置计数器。

建议的解决方案3:使用with语句

我从未使用它,但从我看到的,它用于扫描另一个函数中的try / catch代码。你怎么用这个来重复一些事情呢?我很高兴学习如何使用我的第一个语句:)

建议解决方案4:使用迭代器/生成器,xrange,列表推导......

不,不,不......

如果你写:     [x()in xrange(4)]

你是: 1)为您不关心的值创建列表。 2)提供计数器(_)

如果你写:

for _ in xrange(4):
   X()

见上文第2点)

如果你写:

def repeat(n):
    i = 0
    while i < n : 
        yield i < n
        i+1

那你怎么用重复?像这样 ? :

for x in repeat(5):
    X() 

然后看上面的第2点。此外,这基本上是xrange,所以为什么不使用xrange。

还有其他很酷的想法吗?

有些人问我使用什么语言,因为他们不熟悉这种重复(N)语法。我的主要编程语言是python,但我确信我已经在其他语言中看到过这种语法。访问我的书签,然后访问在线搜索,可以看出以下语言的语法很酷:

Ruby

它只是被称为时代而不是重复。

#!/usr/bin/env ruby

3.times do
  puts "This will be printed 3 times"
end

print "Enter a number: "
num = gets.chomp.to_i

num.times do
  puts "Ruby is great!"
end

Netlogo

 pd repeat 36 [ fd 1 rt 10 ]
 ;; the turtle draws a circle

AppleScript

[applescript]
repeat 3 times
--commands to repeat
end repeat
[/applescript]

Verilog

  1 module repeat_example();
  2 reg  [3:0] opcode;
  3 reg  [15:0] data;
  4 reg        temp;
  5 
  6 always @ (opcode or data)
  7 begin
  8   if (opcode == 10) begin
  9     // Perform rotate
 10     repeat (8) begin 
 11        #1  temp = data[15];
 12       data = data << 1;
 13       data[0] = temp;   
 14     end 
 15   end
 16 end
 17 // Simple test code
 18 initial begin
 19    $display (" TEMP  DATA");
 20    $monitor (" %b     %b ",temp, data);
 21     #1  data = 18'hF0;
 22     #1  opcode = 10;
 23     #10  opcode = 0;
 24     #1  $finish;
 25 end
 26 
 27 endmodule

Rebol

repeat count 50 [print rejoin ["This is loop #: " count]]

Forth

标签10 0做一些LOOP将重复10次,你不必提供计数器(Forth自动将其存储在特殊变量I中)。

   : TEST   10 0 DO  CR ." Hello "  LOOP ;

Groovy

你可以写1.upTo(4){code}或4times {code}来执行代码4次。 Groovy在循环方面是一个爆炸,它有六种方法可以做到(upTo,times,step,java for,groovy for,foreach和while)。

// Using int.upto(max).
0.upto(4, createResult)
assert '01234' == result

// Using int.times.
5.times(createResult)
assert '01234' == result

// Using int.step(to, increment).
0.step 5, 1, createResult
assert '01234' == result

2 个答案:

答案 0 :(得分:3)

警告:请勿在生产中进行此操作!

我强烈建议您使用已经提供的众多列表理解解决方案之一,因为这些解决方案无限少。但是,如果你是冒险的,真的,真的,真的想要这样做,请继续阅读......

我们可以稍微调整您的repeat解决方案,以便嵌套工作,通过存储根据被调用位置而变化的状态。我们怎么做?当然,通过检查堆栈!

import inspect

state = {}

def repeat(limit):
    s = tuple((frame, line) for frame, _, line, _, _, _ in inspect.stack()[1:])
    counter = state.setdefault(s, 0)
    if counter < limit:
        state[s] += 1
        return True
    else:
        del state[s]
        return False

我们通过键入dict元组的元组来设置状态repeat以跟踪调用(stack_frame, line_number)函数的每个唯一位置的当前计数器。这与原始repeat函数有同样的警告,因为break确实打破了所有内容,但在大多数情况下似乎都有效。例如:

while repeat(2):
    print("foo")
    while repeat(3):
        print("bar")

输出:

foo
bar
bar
bar
foo
bar
bar
bar

答案 1 :(得分:2)

当然,你是在思考过度的事情。如果我正确理解你的(相当冗长的)问题,你想避免重复代码。在这种情况下,您的第一个调用端口应该是编写一个函数。这似乎相对简单:你需要的是一个带有参数x的函数(我使用n只是因为它让我想起了整数)并返回一个包含许多输入元素的列表。像(未经测试)的东西:

def read_inputs(n):
    ret_val = []
    for i in range(n):
        ret_val.append(input())
    return retval

您的代码的其余部分只是:

A = read_inputs(X)
B = read_inputs(Y)