10**200 程度の非常に大きな整数があるとします。整数をファイルに保存すると、ある程度のスペースが必要になります。
を使用してイテレータに変換する場合yield
、代わりにイテレータをファイルに保存できますか? これによりリソースが節約されますか?
イテレータは次のように生成できます。
def rec():
for i in range(0,10**200):
yield i
iterable = rec()
10**200 程度の非常に大きな整数があるとします。整数をファイルに保存すると、ある程度のスペースが必要になります。
を使用してイテレータに変換する場合yield
、代わりにイテレータをファイルに保存できますか? これによりリソースが節約されますか?
イテレータは次のように生成できます。
def rec():
for i in range(0,10**200):
yield i
iterable = rec()
これがあなたがやりたいことだと思います:
def f():
yield 10**200
次にf()
、ファイルに保存します。答えはノーです。それはうまくいきません。(注: iterable ではなくジェネレーターです) のようなf()
ジェネレーターは、特殊な目的の pickle 化をサポートするカスタム イテレーターに変換しない限り、pickle 化またはシリアル化できません。
larsmansの回答に基づいて、これを行うためにカスタム イテレータを作成できます。
class my_large_num(object):
def __init__(self):
self.num_iterations = 0
def __iter__(self):
return self
def next(self):
if self.num_iterations < 1:
self.num_iterations += 1
return 10**200
else:
raise StopIteration()
その後、次のことができます。
import pickle
pickled_repr = pickle.dumps(my_large_num())
restored_object = pickle.loads(pickled_repr)
sum(restored_object)
これが機能するのは、反復可能なオブジェクトの下に、完了時に発生するnext()
関数があるStopIteration
ためです。行っているのは、この機能を実装するクラスを作成することだけです。
この特定のケースでは、クラスをファイルに保存したという事実に関係なく、反復を実行し10**200
てメモリに保存する必要があるため、シリアル化せずに実行できるオンデマンドで番号を生成する以外の機能は得られません。オブジェクト。
mmapスタイルの省スペースを考えているかもしれません。これはメモリをファイルにマップします - ただし、これはプログラムの使用可能なメモリに影響を与えることに注意してください。
モジュールを使用してShelve
これを保存できます。
「シェルフ」は永続的な辞書のようなオブジェクトです。「dbm」データベースとの違いは、シェルフ内の値 (キーではありません!) は基本的に任意の Python オブジェクト (pickle モジュールが処理できるものなら何でも) にできることです。
値 10**200 の整数は、大量のスペースを必要としません。Base 10 ASCII でエンコードされ、わずか 201 文字です。データをバイナリで保存する場合は、85 のみを見ています。
「反復可能」を意味する場合、それもあまり意味がありません-反復可能は本質的に関数であり、すでに関数が保存されています-それはソースファイルにあります。