-1

Python辞書を読み書きする簡単な方法を実装しましたが、関数として機能しない理由を理解するのに苦労しています。

辞書を保存するには、次のコマンドを使用します。

def saveHash():
     print "Saving hash file to ./savedHash"
     f = open('savedHash','w')
     f.write(str(my_hash))
     f.close()
     print "Save Successfull"

saveHash()

これは完全に正常に機能します。次に、スクリプト内に辞書をロードします。

def loadHash(name):
     print "Loading hash file %s" % (name)
     f = open(name,'r')
     my_hash = eval(f.read())
     f.close()
     print "Hash loaded"

loadHash('savedHash')

問題は、実行しているスクリプト内では機能しないように見えますが、シェル内では機能することです。savedHashディレクトリ内に/home/dan/あり、そのディレクトリ内でPythonシェルを開いた場合は、orを実行するか、loadHash('savedHash')辞書/ハッシュにデータが入力されません。実行すると失敗し、次のエラーメッセージが返されます。loadHash('./savedHash')loadHash('/home/dan/savedHash')random.choice(my_hash.keys())

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/projects/dan/software/Python-2.7.2/Lib/random.py", line 274, in choice
    return seq[int(self.random() * len(seq))]  # raises IndexError if seq is empty
IndexError: list index out of range

ただし、次のようなコマンドごとに実行すると、次のようになります。

>>> f = open(name,'r')
>>> my_hash = eval(f.read())
>>> f.close()

入力print random.choice(my_hash.keys())して値を取得できます。スクリプト内では機能しないが、シェル内では機能する理由を誰かが知っていますか?ファイル名を取得するために引数パーサーを使用しています。

4

3 に答える 3

4

まず第一にeval、信頼できないソース (ファイルなど) からは絶対に使用しないでください。

辞書を次のように保存することをお勧めしjsonます。

>>> import json
>>> d = {'a': 3}
>>> with open('data.txt', 'w') as fobj:
...   json.dump(d, fobj)
... 
>>> with open('data.txt') as fobj:
...   d2 = json.load(fobj)
... 
>>> d2
{u'a': 3}
于 2012-06-26T20:53:42.473 に答える
2

これは、save 関数でmy_hashは、 がグローバルであると想定され、グローバル名前空間から取得されるためです。これは予想どおりです。ただし、2 番目の関数は、グローバル変数について話していることを知りません。したがって、関数の先頭に追加する必要がありますglobal my_hash

より良い解決策は、ハッシュを引数として関数に渡して保存することです。そしてロード時にそれを返します:

def saveHash(my_hash):
    # ...

def loadHash():
    # ...
    return my_hash

# Usage:
saveHash(my_hash)
my_hash = loadHash()
于 2012-06-26T20:55:27.300 に答える
0

関数loadHash()は何も返さないためmyHash、関数が終了すると変数は消えます。

myHash他の回答で指摘されているように、グローバル変数を設定しようとしている場合はglobal myHash、関数内に行を含める必要があります。可能であればグローバル変数を避ける理由も参照してください。

回避に関する他の回答のメモも参照してくださいeval()

于 2012-06-26T20:52:52.020 に答える