私はこの質問に答えていましたが、私の解決策は次のとおりでした(私はこの答えを投稿しませんでした):
def wordigit(w):
digits = {}
c = itertools.count(1)
for char in w:
if w not in digits:
digits[char] = c.next()
return ''.join(str(i) for i in (digits[char] for char in w))
print ' '.join(wordigit(w) for w in s.split())
一見、これは正しく見えます。しかし、私は誤った結果を得ました:
In [236]: ' '.join(wordigit(w) for w in s.split())
Out[236]: '12345 14345 33345' # notice the numbers in the second "word". 1-4 is not a legal progression for itertools.count. It should have been 12324 instead of 14345
私はこのソリューションをIPythonで開発しました。これは、IPythonが内部で行う最適化のバグである可能性があると考えて、Pythonインタープリターを起動してその内容を確認しました。また、リスト内包表記が異常な動作につながる可能性があると思いました。そこでwordigit
、2回呼び出してみました-2つの等しくない文字列のそれぞれに1回ずつ、次の結果が得られました。
>>> def wordigit(w):
... digits = {}
... c = itertools.count(1)
... for char in w:
... if w not in digits:
... digits[char] = c.next()
... return ''.join(str(i) for i in (digits[char] for char in w))
...
>>> wordigit('areyo')
'12345'
>>> wordigit('uanap')
'14345'
したがって、関数内にオブジェクトを作成してもitertools.count
(したがって、関数は実行のたびにオブジェクトを再作成する必要があります)、関数が戻った後もオブジェクトは何らかの形で存続し、関数が再度呼び出されたときに再初期化せずに再利用されるようです。同様に、これがのdict
「数字」にも当てはまることは明らかですwordigit
。
これはどのように起こっていますか?どういうわけか、この動作は私には意味がありません。
IpythonのPython2.7.1と新しいPython2.7.3インタープリターでこの動作に気づきました