有没有一种类似python的方法来重写下面的代码块?列出理解?

2024-09-19 19:22:37 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在试着做this。 这就是我想到的:

X, Y, A = [x1], [y1], [(x1 + y1) % F]
for i in range(1, N):
  X.append((C * X[i-1] + D * Y[i-1] + E1) % F)
  Y.append((D * X[i-1] + C * Y[i-1] + E2) % F)
  A.append((X[i] + Y[i]) % F)

这项工作,但正如你看到的,它不是很Python。我想知道是否有一种方法可以通过pythonic的方式获得相同的结果,可能是通过使用列表理解。 谢谢


Tags: 方法in列表for方式rangethispythonic
3条回答

如果xy不依赖于A,我可能会尝试为它们创建一个生成器,然后从中构建XYA(或者做任何事情)

def genXYA(n):
    x, y = x1, y1
    for i in range(n):
        nx, ny = (C * x + D * y + E1) % F, (D * x + C * y + E2) % F
        a = (nx + ny) % F
        yield nx, ny, a
        x, y = nx, ny


X, Y, A = map(list, zip(*genXYA(N)))

只是为了解释这里发生了什么

生成器就像一个列表,除了不立即返回所有内容外,它一次只返回一项

函数genXYA(n)返回一个生成器,该生成器在每一步返回元组(x, y, a),并在返回n后停止

现在我们有了这个生成器,我们可以直接创建列表XYA

N = 5,如果你做了list(genXYA(N)),你会得到

[(x2, y2, a1),
 (x3, y3, a2),
 (x4, y4, a3),
 (x5, y5, a4),
 (x6, y6, a5)]

您想要的是将这些列分隔为单独的命名列表。您可以使用zip进行此操作zip获取了许多iterables,并创建了新的iterables,这些iterables是每个iterables的第一个、第二个、第三个,等等

为了给zip提供正确的参数,我们需要解包生成器。这就是*的目的

zip(*genXYA(N))的结果是另一个生成器,但是我们可以通过调用list(zip(*genXYA(N)))来查看其中的内容

[(x2, x3, x4, x5, x6), # => X
 (y2, y3, y4, y5, y6), # => Y
 (a1, a2, a3, a4, a5)] # => A

所以我们离最终结果越来越近了

当我们调用map(list, zip(*genXYA(N)))时,我们是说对于该列表中的所有内容,我们需要每个项目的列表(元组列表是包含元组中所有内容的列表)

map还返回一个生成器,然后我们可以将其解压到所需的变量中


使用生成器的好处是,只在需要时计算下一次迭代,而不必存储所有以前的迭代

例如,如果您只需要A的最后一个值,可以执行以下操作:

for x, y, a in genXYA(N):
    pass
print(a)

使用递归+numpy

import numpy as np

X=np.array([[x1, y1, 1]])
A=np.array([[C, D, E1], [D, C, E2], [1,1,1]])

def myFunc(res, A, F, N):
    res[-1,2]=1
    if(N==1):
        return np.append(res, [A@res[-1]%F], axis=0)
    else:
        N-=1
        return myFunc(np.append(res, [A@res[-1]%F], axis=0), A, F, N)


X, Y=myFunc(X, A, F, N-1)[:, :2].T

A=(X+Y)%F

样本输出:

x1=1
y1=2
C, D, E1, E2, F, N=4,15,6,7,3,11

X=np.array([[x1, y1, 1]])
A=np.array([[C, D, E1], [D, C, E2], [1,1,1]])

X, Y=myFunc(X, A, F, N-1)[:, :2].T
A=(X+Y)%F

print(X)
print(Y)
print(A)
 #outputs:

[1 1 1 1 1 1 1 1 1 1 1]
[2 0 1 2 0 1 2 0 1 2 0]
[0 1 2 0 1 2 0 1 2 0 1]

如果您有两个变量,每个变量都应该使用两个变量的当前值进行更新,那么最好的解决方案是使用并行赋值

X, Y, A = [], [], []
x, y = x1, y1
for i in range(N):
    X.append(x)
    Y.append(y)
    A.append((x + y) % F)
    # update both x and y in parallel
    x, y = (C*x + D*y + E1) % F, (D*x + C*y + E2) % F

相关问题 更多 >