web-dev-qa-db-ja.com

Python)の関数から名前で変数を返します

関数を使用して、指定されたリストを返そうとしています。

def get_ext(file_type):
    text = ['txt', 'doc']
    audio = ['mp3', 'wav']
    video = ['mp4', 'mkv']
    return ?????

get_ext('audio')  #should return de list ['mp3', 'wav']

それから私は立ち往生しています。これは、拡張機能の大きなリストの単純で短い例です。それを行う最も簡単な方法は何ですか?

11
Ludoloco

このようなほとんどの場合、通常の辞書で問題なく動作します。

>>> get_ext = {'text': ['txt', 'doc'],
...            'audio': ['mp3', 'wav'],
...            'video': ['mp4', 'mkv']
... }
>>> 
>>> get_ext['video']
['mp4', 'mkv']

関数が本当に必要な場合(正当な理由がある場合があります)には、いくつかのオプションがあります。最も簡単な方法の1つは、辞書のgetメソッドに割り当てることです。カーテンの後ろの辞書を使用しない場合は、名前get_extを再割り当てすることもできます。

>>> get_ext = get_ext.get
>>> get_ext('video')
['mp4', 'mkv']

不明なキーを入力すると、この関数はデフォルトでNoneを返します。

>>> x = get_ext('binary')
>>> x is None
True

不明なキーの代わりにKeyErrorが必要な場合は、get_ext.__getitem__の代わりにget_ext.getに割り当ててください。

カスタムのデフォルト値が必要な場合、1つのアプローチは、辞書を関数内にラップすることです。この例では、デフォルト値として空のリストを使用しています。

def get_ext(file_type):
    types = {'text': ['txt', 'doc'],
             'audio': ['mp3', 'wav'],
             'video': ['mp4', 'mkv']
    }

    return types.get(file_type, [])

ただし、@ omri_saadonは、types = ...割り当てが関数呼び出しごとに実行されるという有効なコメントを提供しました。これが気になる場合は、これを回避するためにできることは次のとおりです。

class get_ext(object):
    def __init__(self):
        self.types = {'text': ['txt', 'doc'],
                      'audio': ['mp3', 'wav'],
                      'video': ['mp4', 'mkv']
        }

    def __call__(self, file_type):
        return self.types.get(file_type, [])

get_ext = get_ext()

最終的に呼び出し可能オブジェクトは呼び出し可能であるため、これ以降は通常の関数のようにget_extを使用できます。 :)

このアプローチは、self.typesが一度だけ作成されるという事実に加えて、関数が認識するファイルタイプを簡単に変更できるという大きな利点があることに注意してください。

>>> get_ext.types['binary'] = ['bin', 'exe']
>>> get_ext('binary')
['bin', 'exe']
30
timgeb

_@timgeb's answer_ のようにdictionaryを定義したくない場合は、local()を呼び出すと、現在使用可能なdictionaryvariablesが得られます。

_def get_ext(file_type):
    text = ['txt', 'doc']
    audio = ['mp3', 'wav']
    video = ['mp4', 'mkv']
    return locals()[file_type]
_

そしてそれが機能することを示すためのテスト:

_>>> get_ext("text")
['txt', 'doc']
_
9
Joe Iddon

次のように、タプル/リスト値でdictを簡単に使用できます。

def get_ext(file_type):
    d = {'text': ['txt', 'doc'],
         'audio': ['mp3', 'wav'],
         'video': ['mp4', 'mkv']}
    return d[file_type]


print(get_ext('audio'))
3
Jump3r

@timgebの回答によると、私は辞書を使用しますが、頻繁にアクセスする場合は、速度に注意し、キャッシュを使用できるクラスを定義したくない場合。

from functools import lru_cache

def get_ext(file_type):
    d = {'text': ['txt', 'doc'],
         'audio': ['mp3', 'wav'],
         'video': ['mp4', 'mkv']}
    return d[file_type]

@lru_cache(maxsize=3, typed=False)
def get_ext_cached(file_type):
    d = {'text': ['txt', 'doc'],
         'audio': ['mp3', 'wav'],
         'video': ['mp4', 'mkv']}
    return d[file_type]

from timeit import timeit

# non cached
print(timeit(stmt='get_ext("text")', globals={'get_ext': get_ext}))
# 0.48447531609922706 on my machine

# cached
print(timeit(stmt='get_ext("text")', globals={'get_ext': get_ext_cached}))
# 0.11434909792297276

この特定のケースでは、やり過ぎである可能性が高く、辞書でgetを直接呼び出すことができます(キャッシュは独自の辞書を作成し、それを正確に実行します)。

d = {'text': ['txt', 'doc'],
    'audio': ['mp3', 'wav'],
    'video': ['mp4', 'mkv']}

# 0.05016115184298542
print(timeit(stmt="d['text']",
             globals={'d':d,'c':c}))
1
Alex Stasse

辞書を使用する:

def get_ext(file_type):
    d = {'text' : ['txt', 'doc'],
         'audio' : ['mp3', 'wav'],
         'video' : ['mp4', 'mkv']}
    try:
        return d[file_type]
    except KeyError:
        return []

get_ext('audio') # ['mp3', 'wav']

キーが存在しない場合は空のリストを返します。しかし、これが私の頭に浮かんだ最も単純な答えです。より良い答えについては、@ timgebの答えを参照してください。

1
ᴀʀᴍᴀɴ