web-dev-qa-db-fra.com

Renvoie une variable par nom d'une fonction en Python

J'essaie de retourner une liste donnée avec une fonction.

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

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

Alors je suis coincé. Ceci est un exemple simple/court d'une grande liste d'extensions . Quel est le moyen le plus simple de le faire?

10
Ludoloco

Dans la plupart des cas, un dictionnaire ordinaire fera très bien l'affaire.

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

Si vous voulez vraiment ou avez besoin d’une fonction (pour laquelle il peut y avoir des raisons valables), vous avez deux options. Une des plus faciles consiste à affecter à la méthode get du dictionnaire. Vous pouvez même réaffecter le nom get_ext si vous n'avez pas utilisé le dictionnaire derrière le rideau.

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

Cette fonction retournera None par défaut si vous entrez une clé inconnue:

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

Si vous souhaitez plutôt utiliser une KeyError pour les clés inconnues, affectez-le à get_ext.__getitem__ au lieu de get_ext.get.

Si vous voulez une valeur par défaut personnalisée, une approche consiste à envelopper le dictionnaire dans une fonction. Cet exemple utilise une liste vide comme valeur par défaut.

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

    return types.get(file_type, [])

Cependant, @omri_saadon a fait remarquer que l’affectation types = ... est effectuée à chaque appel de fonction. Voici ce que vous pouvez faire pour contourner cela si cela vous dérange.

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()

Vous pouvez utiliser get_ext comme une fonction normale à partir de maintenant, car les callables sont finalement des callables. :)

Notez que cette approche - outre le fait que self.types n'est créé qu'une seule fois - présente l'avantage considérable de pouvoir changer facilement les types de fichiers reconnus par votre fonction.

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

Si vous ne souhaitez pas définir une dictionary comme dans @timgeb's answer , vous pouvez appeler local() qui vous donne une dictionary de la variables actuelle disponible.

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

et un test pour montrer que cela fonctionne:

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

Vous pouvez facilement utiliser dict avec les valeurs Tuple/list comme ceci:

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

Selon la réponse de @timgeb, j'utiliserais un dictionnaire, mais si vous en avez beaucoup accès, accordez une importance particulière à la rapidité et ne souhaitez pas définir de classe, vous pouvez utiliser la mise en cache.

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

Bien que dans ce cas particulier, il y ait probablement trop de ressources et vous pouvez simplement appeler get sur le dictionnaire directement (le cache construit simplement son propre dictionnaire et le fait exactement), vous pouvez l'utiliser à l'avenir pour toutes les fonctions pures qui sont effectivement une recherche calculée.

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

Utilise le dictionnaire:

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']

retourne une liste vide dans le cas où cette clé n'existe pas . quelle que soit la réponse la plus simple qui me vienne à l'esprit, pour une meilleure réponse, voir @timgeb answer.

1
ᴀʀᴍᴀɴ