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

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

ただいまの
回答率

90.49%

  • Python

    8489questions

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

  • Python 3.x

    6831questions

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

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

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 648

miyahan

score 2945

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

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

"""class変数を使ったコード."""
import csv

csv_content = """だいこん,128
にんじん,38
たまねぎ,38
なす,48
きゅうり,28"""


class Yasai(object):
    @classmethod
    def _load_csv(cls):
        if not hasattr(cls, 'caches'):
            print('init')
            cls.caches = {row[0]: row[1] for row in csv.reader(csv_content.split())}

    @classmethod
    def get_price(cls, item):
        cls._load_csv()
        return cls.caches.get(item) or None


>>> from hoge import Yasai
>>> Yasai.get_price('にんじん')
init
'38'
>>> Yasai.get_price('にんじん')
'38'

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

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

"""みようみまねでデコレータを使ったコード."""
def _yasai_cache(func):
    print('init')
    caches = {row[0]: row[1] for row in csv.reader(csv_content.split())}
    def __yasai_cache(item):
        return caches.get(item) or None
    return __yasai_cache

@_yasai_cache
def get_price(yasai):
    pass


>>> from hoge import get_price
init
>>> get_price('にんじん')
'38'
>>> get_price('にんじん')
'38'

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

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

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+3

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/18 23: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
    ```

    キャンセル

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

  • ただいまの回答率 90.49%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 解決済

    Kerasで学習済みモデルを初期化できない

    kerasを使って学習済みモデルの評価をしようとしています。しかし、重みを設定するとタイトルのようなエラーが出てしまいました。フィルタ数、つまり最初のnOutoutPlaneは32

  • 受付中

    pythonでmysqlconnectorを使う際

    pythonでmysqlを操作して、日本語を取り出しその後それをcsvに書き込みたいのですが、 res = cursor.fetchall() で取り出した後に、どこかで .

  • 解決済

    python エラーわからない

    clsの引数の位置がおかしいと英訳のチェックと原因が知りたいです。よろしくおねがいいたします # user_name = "olga" # user_score = 10

  • 解決済

    Django views.pyに記述される変数について

    vews.pyの変数について 大変失礼致します。 現在、勉強も兼ねてDjangoを使ってwebサイトを構築しているのですが、リクエストで呼び出されている度にviews.pyのグ

  • 解決済

    pythonのスライスについて

    a = b[:,0] このようなコードがあったとき、どのようなことがおこなわれますか? bはこのコードがなりたつ何かだとすると なにだったら成り立ちますか? すみません、間

  • 解決済

    Python クラス内でクラスメソッドを使用したい

    題意の通り、クラス内でクラスメソッドを使用したいのですができません。下記に例を示しています。 これを実現するにはどうすれば良いでしょうか? class Test: _

  • 解決済

    python3 クラスを呼び出すとクラス内の処理を全て実行する

    クラスを呼び出すと自動で、クラス内の処理[関数1,関数2]を実行したいと思います。 class Hello(): @classmethod def Sain(

  • 解決済

    csvの特定の行を削除したい、書き込みをしたい

     csvの特定の行を削除したい、書き込みをしたい csvデータを作成する際に下記のプログラムを作成し nsx = [195,20,0] import csv with open

同じタグがついた質問を見る

  • Python

    8489questions

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

  • Python 3.x

    6831questions

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