質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

5850閲覧

初回時にデータロードし2回目以降はキャッシュから返えす関数

miyahan

総合スコア3095

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2017/09/17 18:00

編集2017/09/19 03:12

PythonでCSVを読み込んでDBにインポートするコードを書いています。1回の実行で何度もランダムアクセスする必要があるため最初にCSVを全て読みんで辞書に格納しておき、それ以降はその辞書から値を探して返すようにしたいです。

そのキャッシュをグローバル空間に置くのは何なのでクラス変数を使おうと以下のように実装しました。

python

1"""class変数を使ったコード.""" 2import csv 3 4csv_content = """だいこん,128 5にんじん,38 6たまねぎ,38 7なす,48 8きゅうり,28""" 9 10 11class Yasai(object): 12 @classmethod 13 def _load_csv(cls): 14 if not hasattr(cls, 'caches'): 15 print('init') 16 cls.caches = {row[0]: row[1] for row in csv.reader(csv_content.split())} 17 18 @classmethod 19 def get_price(cls, item): 20 cls._load_csv() 21 return cls.caches.get(item) or None 22 23 24>>> from hoge import Yasai 25>>> Yasai.get_price('にんじん') 26init 27'38' 28>>> Yasai.get_price('にんじん') 29'38'

やりたいことは実現できているのですが、少し実装がおおげさに感じます。

調べたところ関数の結果をキャッシュするデコレーター:memonize というテクニックがあることを知りましたが、恥ずかしながらデコレーターを理解しきれておらず、これまた変なコードになってしまいました。またファイル(モジュール)をインポートしただけで初回ロードが走るのも少し気になります。

python

1"""みようみまねでデコレータを使ったコード.""" 2def _yasai_cache(func): 3 print('init') 4 caches = {row[0]: row[1] for row in csv.reader(csv_content.split())} 5 def __yasai_cache(item): 6 return caches.get(item) or None 7 return __yasai_cache 8 9@_yasai_cache 10def get_price(yasai): 11 pass 12 13 14>>> from hoge import get_price 15init 16>>> get_price('にんじん') 17'38' 18>>> get_price('にんじん') 19'38'

もう少しシンプルな実装やセオリー(デザインパターン?)はあれば教えてください。

なお実際は複数のCSVを比較したりチェックしたりしながらインポートを行っているため、CSVまるごとDBにえいやと入れたりすることはできません。

※今のクラス変数を使う方法でいいんじゃない?という場合もその旨を回答いただけると幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

組み込みで lru_cache というのが用意されています。

https://docs.python.jp/3/library/functools.html

投稿2017/09/18 00:09

driller

総合スコア720

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

miyahan

2017/09/18 14:32

様々なサイトで解説されている memonize ですが、組み込みのデコレータが用意されてるんですね。 データをプリロードする関数にこのデコレーターをセットして、キャッシュの塊をキャッシュヒットさせて返させる感じでしょうか。巨大な辞書が飛び交うのは少し気になりますが、読むだけならただの参照渡しでメモリも使いませんしアリかもしれませんね。 ```python @lru_cache(maxsize=1) def _load_cache(): return {row[0]: row[1] for row in csv.reader(csv_content.split())} def get_yasai_price(item): return _load_cache().get(item) or None ```
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問