【问题标题】:Iteration Issues When Looping Through A List of Tuple循环遍历元组列表时的迭代问题
【发布时间】:2019-08-24 03:14:18
【问题描述】:

我已经生成了这个函数,我正在传递一些输入参数(i,j,t),我用它做了一些事情。现在,如果您查看输出,您会发现我有一些标记为 Test1 和 Test2 的打印函数,而我感到困惑的是为什么这两个测试之间存在差异,因为从我的角度来看,它们应该打印相同的精确值输入(1,1,1)的东西。

第一轮测试两个结果差不多,很棒。然而,在那次测试之后,我输入的输入参数似乎从 (1,1,1) 更新为 (2,2,1)。这个奇怪的更新似乎也发生在第一个 for 循环的开头,我希望尝试了解为什么会发生这个更新。

我真的不需要固定代码,因为在函数开头引入 x_coord 和 y_coord 变量似乎可以缓解我遇到的问题并按照我的意愿去做。但是,如果有人可以帮助我理解为什么会发生“i”和“j”输入的更新以及为什么测试打印语句不完全相同,那就太好了!

model = ConcreteModel()

Imax = 3
Jmax = 3
Tmax = 1

model.Iset = RangeSet(1,Imax) #e.g. i = {1, 2, 3}
model.Jset = RangeSet(1,Jmax)
model.Tset = RangeSet(1,Tmax)
model.immigration = Var(model.Iset, model.Jset, model.Tset, initialize = 1)
model.inf_b4treat = Var(model.Iset, model.Jset, model.Tset, initialize=1)
model.foo = Var(model.Iset, model.Jset, model.Tset, initialize=1)



def get_neighbours(i,j,t): 

    x_coord = i
    y_coord = j
    rowbound = Imax + 1
    colbound = Jmax + 1

    neighbours = [
        (i - 1, j - 1, t), (i - 1, j, t), (i - 1, j + 1, t),
        (i, j - 1, t), (i, j + 1, t),
        (i + 1, j - 1, t), (i + 1, j, t), (i + 1, j + 1, t),
    ]
    print(f"Neighbours of cell ({i},{j},{t}): {neighbours}")
    print("")

    valid_tuples = []
    invalid_tuples = []
    # for each tuple in neighbours, we will print out the good and bad coordinates.

    print(f"First.Test1 = ({i},{j},{t})")
    print(f"First.Test2 = ({x_coord},{y_coord},{t})")
    print("")

    for (i,j,t) in neighbours:
        if not 0 < i < rowbound or not 0 < j < colbound:
            #print(f"Invalid Tuple --> ({i},{j},{t})")
            invalid_tuples.append((i,j,t))

        else:
            #print(f"Valid Tuple --> ({i},{j},{t})")
            valid_tuples.append((i,j,t))

    print(f"Second.Test1 = ({i},{j},{t}) ")
    print(f"Second.Test2 = ({x_coord},{y_coord},{t})")
    print("")

    print(f"Invalid Tuples: {invalid_tuples}")   
    print(f"Valid Tuples:   {valid_tuples}")
    print("")

    immigration_value_ijt = 0
    for (i,j,t) in valid_tuples:
        immigration_value_ijt += value(model.inf_b4treat[i,j,t])
    print(f"Quantity Immigrating to cell.Test1 ({i},{j},{t}): {immigration_value_ijt}")        
    print(f"Quantity Immigrating to cell.Test2 ({x_coord},{y_coord},{t}): {immigration_value_ijt}")
    print("")
    print(f"Third.Test1 = ({i},{j},{t})")
    print(f"Third.Test2 = ({x_coord},{y_coord},{t})")
    print("")    

get_neighbours(1,1,1)

输出:

Neighbours of cell (1,1,1): [(0, 0, 1), (0, 1, 1), (0, 2, 1), (1, 0, 1), (1, 2, 1), (2, 0, 1), (2, 1, 1), (2, 2, 1)]

First.Test1 = (1,1,1)
First.Test2 = (1,1,1)

Second.Test1 = (2,2,1) 
Second.Test2 = (1,1,1)

Invalid Tuples: [(0, 0, 1), (0, 1, 1), (0, 2, 1), (1, 0, 1), (2, 0, 1)]
Valid Tuples:   [(1, 2, 1), (2, 1, 1), (2, 2, 1)]

Quantity Immigrating to cell.Test1 (2,2,1): 3
Quantity Immigrating to cell.Test2 (1,1,1): 3

Third.Test1 = (2,2,1)
Third.Test2 = (1,1,1)

【问题讨论】:

    标签: python function input tuples


    【解决方案1】:

    您正在使用 for 循环隐藏 i,j,t 并且循环在每次迭代时设置新值。所以最终的结果是邻居列表的最后一个条目。

    这里有一些打印语句显示正在发生的事情:

    def test_func(a, b, c):
        l1 = [(0, 0, 1), (0, 1, 2), (2, 2, 1)]
        print(f'Before a {a} id {id(a)}, b {b} id {id(b)}, c {c} id {id(c)}\n')
        # since three variable are specified, each tuple entry is unpacked
        # into the variables, which are a, b and c
        for (a, b, c) in l1:  # The parenthesis don't do anything and aren't needed
            print(f'Inside a {a} id {id(a)}, b {b} id {id(b)}, c {c} id {id(c)}')
            print(f'Inside a is type {type(a)}')
        print(f'\nAfter a {a} id {id(a)}, b {b} id {id(b)}, c {c} id {id(c)}')
    
        # just a single variable name would be the entire tuple
        for entry_tuple in l1:  # The parenthesis don't do anything and aren't needed
            print(f'Entry tuple is {entry_tuple}  and the type is {type(entry_tuple)}')
    
        print(f'At end a is type {type(a)}')
    
    
    test_func(1, 1, 1)
    

    输出:

    Before a 1 id 94439557494624, b 1 id 94439557494624, c 1 id 94439557494624
    
    Inside a 0 id 94439557494592, b 0 id 94439557494592, c 1 id 94439557494624
    Inside a is type <class 'int'>
    Inside a 0 id 94439557494592, b 1 id 94439557494624, c 2 id 94439557494656
    Inside a is type <class 'int'>
    Inside a 2 id 94439557494656, b 2 id 94439557494656, c 1 id 94439557494624
    Inside a is type <class 'int'>
    
    After a 2 id 94439557494656, b 2 id 94439557494656, c 1 id 94439557494624
    Entry tuple is (0, 0, 1)  and the type is <class 'tuple'>
    Entry tuple is (0, 1, 2)  and the type is <class 'tuple'>
    Entry tuple is (2, 2, 1)  and the type is <class 'tuple'>
    At end a is type <class 'int'>
    

    这就是你想知道的吗?

    【讨论】:

    • 我这么认为?但我也会等着看其他人怎么说。我正在阅读我的 for 循环的方式就像“对于邻居中的每个元组 (i,j,t),如果它满足条件 1,它会附加到 invalid_tuples,如果它满足条件 2,那么它会附加到 valid_tuples”跨度>
    • 我想我对如何迭代列表中的元组的理解可能不准确。上面的评论是我希望发生的,而不是实际更新输入参数的原始值。
    • 是的,但是通过在邻居中说 for (i,j,t) - for 循环在每次迭代时更新 i,j 和 t 的值(for 循环的美妙之处)。您应该使用其他变量名称。您正在迭代邻居中的元组,而不是 i,j,t - 邻居中的元组是不可变的。输入参数不是元组,只是整数 - 否则会引发错误。
    • 噢噢噢!好的,我明白你现在在说什么了。我在 for 循环中使用不同的变量运行代码,我得到的测试函数是完全相同的。所以这与元组是不可变对象的概念有关。
    • 根据您的第一条评论 - 我认为您错过了 for 循环实际上循环遍历邻居列表的每个条目(这是一个元组列表)并将该条目放在您说对的变量中在for 之后,允许你对每个条目做一些事情。
    猜你喜欢
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 2019-01-25
    • 1970-01-01
    • 2018-02-13
    • 1970-01-01
    相关资源
    最近更新 更多