符合Python的竞争条件

时间:2015-04-02 00:14:25

标签: python markov

我有一个有趣的问题。我是 - 因为吵闹和咯咯笑 - 试图很快写出一个程序。我把它归结为2行,但它有竞争条件,我无法弄清楚原因。以下是它的要点:

imports...
...[setattr(__main__, 'f', [1, 2, ..]), reduce(...random.choice(f)...)][1]...

每隔一段时间,就会生成以下异常。但不总是。这是我的问题。我怀疑执行的顺序并不能保证,特别是因为我使用了列表技巧 - 我会假设解释器可以预测setattr()返回None并知道我只选择列表中的第二个东西,所以它将实际的setattr()推迟到以后。但它有时只会发生。有任何想法吗? CPython会自动解决一些事情,例如map,filter,reduce calls吗?

Traceback (most recent call last):
  File "/usr/lib64/python3.4/random.py", line 253, in choice
    i = self._randbelow(len(seq))
  File "/usr/lib64/python3.4/random.py", line 230, in _randbelow
    r = getrandbits(k)          # 0 <= r < 2**k
ValueError: number of bits must be greater than zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "test4.py", line 2, in <module>
    print(" ".join([setattr(n,'f',open(sys.argv[1],"r").read().replace("\n"," ").split(" ")),setattr(n,'m',c.defaultdict(list)),g.reduce(lambda p,e:p+[r.choice(m[p[-1]])],range(int(sys.argv[2])),[r.choice(list(filter(lambda x:[m[x[0]].append(x[1]),x[0].isupper()][1],zip(f[:-1],f[1:]))))[0]])][2]))
  File "test4.py", line 2, in <lambda>
    print(" ".join([setattr(n,'f',open(sys.argv[1],"r").read().replace("\n"," ").split(" ")),setattr(n,'m',c.defaultdict(list)),g.reduce(lambda p,e:p+[r.choice(m[p[-1]])],range(int(sys.argv[2])),[r.choice(list(filter(lambda x:[m[x[0]].append(x[1]),x[0].isupper()][1],zip(f[:-1],f[1:]))))[0]])][2]))
  File "/usr/lib64/python3.4/random.py", line 255, in choice
    raise IndexError('Cannot choose from an empty sequence')
IndexError: Cannot choose from an empty sequence

我尝试使用setattr()修改globals()和vars()insetad,但这似乎没有帮助(相同的异常序列)。

这是实际的代码:

import sys,collections as c,random as r,functools as g,__main__ as n
print(" ".join([setattr(n,'f',open(sys.argv[1],"r").read().replace("\n"," ").split(" ")),setattr(n,'m',c.defaultdict(list)),g.reduce(lambda p,e:p+[r.choice(m[p[-1]])],range(int(sys.argv[2])),[r.choice(list(filter(lambda x:[m[x[0]].append(x[1]),x[0].isupper()][1],zip(f[:-1],f[1:]))))[0]])][2]))

如果你有点好奇:这是读取文本文件,生成马尔可夫模型,并吐出一个句子。

2 个答案:

答案 0 :(得分:1)

random.choice()

嗯,当然这是不确定的。如果你非常小心,可以将伪随机数生成器的种子设置为常量,并希望每次都构造相同的序列。它很有可能会起作用。

random.seed(42); ...

答案 1 :(得分:1)

好吧,这是实际发生的事情:在我的句子生成中,我有时会打到文件中的最后一个单词(在某些情况下,取决于文件,没有可能的后继状态)。因此,在这种情况下,我试图从空列表中进行选择。