¿Cómo puedo seleccionar una variable por nombre (cadena)?

Resuelto Ludoloco asked hace 7 años • 5 respuestas

Quiero devolver una lista predeterminada de mi función, según la entrada de la cadena.

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

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

¿Cuál es la forma más sencilla de hacerlo?


Para el problema relacionado de intentar usar cadenas para asignar o crear variables, consulte ¿Cómo creo variables variables? . Esta pregunta trata sobre buscarlos.

Para realizar búsquedas en un objeto existente (en lugar de en las variables locales actuales), consulte Cómo acceder al atributo del objeto dada la cadena correspondiente al nombre de ese atributo .

Ludoloco avatar Nov 26 '17 20:11 Ludoloco
Aceptado

En la mayoría de casos como éste, un diccionario común y corriente funcionará perfectamente.

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

Si realmente desea o necesita una función (para la cual puede haber razones válidas), tiene un par de opciones. Uno de los más sencillos es asignarlo al getmétodo del diccionario. Incluso puedes reasignar el nombre get_extsi no utilizas el diccionario detrás de la cortina.

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

Esta función volverá Nonede forma predeterminada si ingresa una clave desconocida:

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

Si desea un KeyErrorlugar para claves desconocidas, asigne a get_ext.__getitem__en lugar de get_ext.get.

Si desea un valor predeterminado personalizado, un enfoque es envolver el diccionario dentro de una función. Este ejemplo utiliza una lista vacía como valor predeterminado.

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

    return types.get(file_type, [])

Sin embargo, @omri_saadon dio el comentario válido de que la types = ...asignación se realiza en cada llamada de función. Esto es lo que puede hacer para solucionarlo si esto le molesta.

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

Puede usarla get_extcomo una función normal a partir de ahora, porque al final los invocables son invocables. :)

Tenga en cuenta que este enfoque, además del hecho de que self.typessólo se crea una vez, tiene la considerable ventaja de que aún puede cambiar fácilmente los tipos de archivos que reconoce su función.

>>> get_ext.types['binary'] = ['bin', 'exe']
>>> get_ext('binary')
['bin', 'exe']
timgeb avatar Nov 26 '2017 13:11 timgeb

Si no desea definir un dictionaryas en @timgeb's answer, puede llamar a locals(), lo que le proporciona una dictde las variables disponibles en el ámbito local.

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

y una prueba para demostrar que funciona:

>>> get_ext("text")
['txt', 'doc']
Joe Iddon avatar Nov 26 '2017 13:11 Joe Iddon

Puedes usar fácilmente dict con valores de tupla/lista como este:

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


print(get_ext('audio'))
Jump3r avatar Nov 26 '2017 13:11 Jump3r

Usa un diccionario:

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

devuelve una lista vacía en caso de que esa clave no exista. Sin embargo, esta es la respuesta más simple que se me ocurrió; para obtener una mejor respuesta, consulte la respuesta de @timgeb.

ᴀʀᴍᴀɴ avatar Nov 26 '2017 13:11 ᴀʀᴍᴀɴ